From ffb3c049e288cf0b6e9980cd3a2d79b9744664f3 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 16 Aug 2019 13:28:34 -0700 Subject: [PATCH 1/5] Add generation for all IOperation nodes. --- .../CSharp/Portable/CSharpExtensions.cs | 2 +- .../Operations/CSharpOperationFactory.cs | 5 +- .../CSharpOperationFactory_Methods.cs | 6 +- .../Operations/CSharpOperationNodes.cs | 52 +- .../Diagnostics/OperationTests.cs | 18 +- .../Generated/Operations.Generated.cs | 5544 +++++++++- .../Operations/ControlFlowGraphBuilder.cs | 175 +- .../Core/Portable/Operations/Operation.cs | 24 +- .../Portable/Operations/OperationCloner.cs | 27 +- .../Operations/OperationInterfaces.xml | 269 +- .../Portable/Operations/OperationNodes.cs | 9337 +---------------- .../Operations/VisualBasicOperationFactory.vb | 2 +- .../VisualBasicOperationFactory_Methods.vb | 4 +- .../Operations/VisualBasicOperationNodes.vb | 24 +- .../Portable/VisualBasicExtensions.vb | 2 +- .../Compilation/OperationTreeVerifier.cs | 4 +- .../IOperationClassWriter.Verifier.cs | 84 + .../IOperationClassWriter.cs | 461 +- .../Source/IOperationGenerator/Model.cs | 17 +- 19 files changed, 6715 insertions(+), 9342 deletions(-) create mode 100644 src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs diff --git a/src/Compilers/CSharp/Portable/CSharpExtensions.cs b/src/Compilers/CSharp/Portable/CSharpExtensions.cs index 591b48b785aa1..e3062343b1029 100644 --- a/src/Compilers/CSharp/Portable/CSharpExtensions.cs +++ b/src/Compilers/CSharp/Portable/CSharpExtensions.cs @@ -696,7 +696,7 @@ public static Conversion GetConversion(this IConversionOperation conversionExpre { if (conversionExpression.Language == LanguageNames.CSharp) { - return (Conversion)((BaseConversionOperation)conversionExpression).ConvertibleConversion; + return (Conversion)((BaseConversionOperation)conversionExpression).ConversionConvertible; } else { diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index 124c177a8425a..53c8b441234b3 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -1387,12 +1387,11 @@ private IPropertyInitializerOperation CreateBoundPropertyEqualsValueOperation(Bo { ImmutableArray initializedProperties = ImmutableArray.Create(boundPropertyEqualsValue.Property); BoundNode value = boundPropertyEqualsValue.Value; - OperationKind kind = OperationKind.PropertyInitializer; SyntaxNode syntax = boundPropertyEqualsValue.Syntax; ITypeSymbol type = null; Optional constantValue = default(Optional); bool isImplicit = boundPropertyEqualsValue.WasCompilerGenerated; - return new CSharpLazyPropertyInitializerOperation(this, value, boundPropertyEqualsValue.Locals.As(), initializedProperties, kind, _semanticModel, syntax, type, constantValue, isImplicit); + return new CSharpLazyPropertyInitializerOperation(this, value, boundPropertyEqualsValue.Locals.As(), initializedProperties, _semanticModel, syntax, type, constantValue, isImplicit); } private IParameterInitializerOperation CreateBoundParameterEqualsValueOperation(BoundParameterEqualsValue boundParameterEqualsValue) @@ -2073,7 +2072,7 @@ internal IOperation CreatePropertySubpatternMember(Symbol symbol, ITypeSymbol ma var receiver = new InstanceReferenceOperation( InstanceReferenceKind.PatternInput, _semanticModel, nameSyntax, matchedType, constantValue: default, isImplicit: true); return new PropertyReferenceOperation( - property, receiver, ImmutableArray.Empty, _semanticModel, nameSyntax, property.Type, + property, ImmutableArray.Empty, receiver, _semanticModel, nameSyntax, property.Type, constantValue: default, isImplicit: isImplicit); } default: diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs index 42cbce39765fa..5abb1a2d58d9c 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs @@ -402,8 +402,8 @@ internal ImmutableArray GetAnonymousObjectCreationInitializers( // No matching declaration, synthesize a property reference to be assigned. target = new PropertyReferenceOperation( property, - instance, arguments: ImmutableArray.Empty, + instance, semanticModel: _semanticModel, syntax: value.Syntax, type: property.Type, @@ -414,8 +414,8 @@ internal ImmutableArray GetAnonymousObjectCreationInitializers( else { target = new PropertyReferenceOperation(anonymousProperty.Property, - instance, ImmutableArray.Empty, + instance, _semanticModel, anonymousProperty.Syntax, anonymousProperty.Type, @@ -428,7 +428,7 @@ internal ImmutableArray GetAnonymousObjectCreationInitializers( ITypeSymbol assignmentType = target.Type; Optional constantValue = value.ConstantValue; bool isRef = false; - var assignment = new SimpleAssignmentOperation(target, isRef, value, _semanticModel, assignmentSyntax, assignmentType, constantValue, isImplicitAssignment); + var assignment = new SimpleAssignmentOperation(isRef, target, value, _semanticModel, assignmentSyntax, assignmentType, constantValue, isImplicitAssignment); builder.Add(assignment); } diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs index d1a01c394c936..4bb7274efae6a 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs @@ -169,7 +169,7 @@ internal sealed class CSharpLazyArrayInitializerOperation : LazyArrayInitializer private readonly BoundArrayInitialization _arrayInitialization; internal CSharpLazyArrayInitializerOperation(CSharpOperationFactory operationFactory, BoundArrayInitialization arrayInitialization, SemanticModel semanticModel, SyntaxNode syntax, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, constantValue, isImplicit) + base(semanticModel, syntax, type: null, constantValue, isImplicit) { _operationFactory = operationFactory; _arrayInitialization = arrayInitialization; @@ -531,7 +531,7 @@ internal sealed class CSharpLazyVariableInitializerOperation : LazyVariableIniti private readonly BoundNode _value; internal CSharpLazyVariableInitializerOperation(CSharpOperationFactory operationFactory, BoundNode value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + base(locals: ImmutableArray.Empty, semanticModel, syntax, type, constantValue, isImplicit) { _operationFactory = operationFactory; _value = value; @@ -549,7 +549,7 @@ internal sealed class CSharpLazyFieldInitializerOperation : LazyFieldInitializer private readonly BoundNode _value; internal CSharpLazyFieldInitializerOperation(CSharpOperationFactory operationFactory, BoundNode value, ImmutableArray locals, ImmutableArray initializedFields, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, initializedFields, kind, semanticModel, syntax, type, constantValue, isImplicit) + base(initializedFields, locals, semanticModel, syntax, type, constantValue, isImplicit) { _operationFactory = operationFactory; _value = value; @@ -608,7 +608,7 @@ internal sealed class CSharpLazyForEachLoopOperation : LazyForEachLoopOperation private readonly BoundForEachStatement _forEachStatement; internal CSharpLazyForEachLoopOperation(CSharpOperationFactory operationFactory, BoundForEachStatement forEachStatement, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + base(LoopKind.ForEach, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) { _operationFactory = operationFactory; _forEachStatement = forEachStatement; @@ -679,7 +679,7 @@ internal sealed class CSharpLazyIncrementOrDecrementOperation : LazyIncrementOrD private readonly BoundNode _target; internal CSharpLazyIncrementOrDecrementOperation(CSharpOperationFactory operationFactory, BoundNode target, bool isDecrement, bool isPostfix, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(isDecrement, isPostfix, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) + base(isPostfix, isLifted, isChecked, operatorMethod, isDecrement ? OperationKind.Decrement : OperationKind.Increment, semanticModel, syntax, type, constantValue, isImplicit) { _operationFactory = operationFactory; _target = target; @@ -1069,7 +1069,7 @@ internal sealed class CSharpLazyParameterInitializerOperation : LazyParameterIni private readonly BoundNode _value; internal CSharpLazyParameterInitializerOperation(CSharpOperationFactory operationFactory, BoundNode value, ImmutableArray locals, IParameterSymbol parameter, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, parameter, kind, semanticModel, syntax, type, constantValue, isImplicit) + base(parameter, locals, semanticModel, syntax, type, constantValue, isImplicit) { _operationFactory = operationFactory; _value = value; @@ -1086,8 +1086,8 @@ internal sealed class CSharpLazyPropertyInitializerOperation : LazyPropertyIniti private readonly CSharpOperationFactory _operationFactory; private readonly BoundNode _value; - internal CSharpLazyPropertyInitializerOperation(CSharpOperationFactory operationFactory, BoundNode value, ImmutableArray locals, ImmutableArray initializedProperties, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, initializedProperties, kind, semanticModel, syntax, type, constantValue, isImplicit) + internal CSharpLazyPropertyInitializerOperation(CSharpOperationFactory operationFactory, BoundNode value, ImmutableArray locals, ImmutableArray initializedProperties, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(initializedProperties, locals, semanticModel, syntax, type, constantValue, isImplicit) { _operationFactory = operationFactory; _value = value; @@ -1148,7 +1148,7 @@ internal sealed class CSharpLazySingleValueCaseClauseOperation : LazySingleValue private readonly BoundNode _value; internal CSharpLazySingleValueCaseClauseOperation(CSharpOperationFactory operationFactory, BoundNode value, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(label, semanticModel, syntax, type, constantValue, isImplicit) + base(CaseKind.SingleValue, label, semanticModel, syntax, type, constantValue, isImplicit) { _operationFactory = operationFactory; _value = value; @@ -1245,7 +1245,7 @@ internal sealed class CSharpLazyTupleOperation : LazyTupleOperation private readonly BoundTupleExpression _tupleExpression; internal CSharpLazyTupleOperation(CSharpOperationFactory operationFactory, BoundTupleExpression tupleExpression, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, ITypeSymbol naturalType, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, naturalType, constantValue, isImplicit) + base(naturalType, semanticModel, syntax, type, constantValue, isImplicit) { _operationFactory = operationFactory; _tupleExpression = tupleExpression; @@ -1442,7 +1442,7 @@ internal sealed class CSharpLazyWhileLoopOperation : LazyWhileLoopOperation private readonly BoundConditionalLoopStatement _conditionalLoopStatement; internal CSharpLazyWhileLoopOperation(CSharpOperationFactory operationFactory, BoundConditionalLoopStatement conditionalLoopStatement, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, bool conditionIsTop, bool conditionIsUntil, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, continueLabel, exitLabel, conditionIsTop, conditionIsUntil, semanticModel, syntax, type, constantValue, isImplicit) + base(conditionIsTop, conditionIsUntil, LoopKind.While, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) { _operationFactory = operationFactory; _conditionalLoopStatement = conditionalLoopStatement; @@ -1495,7 +1495,7 @@ internal sealed class CSharpLazyConstantPatternOperation : LazyConstantPatternOp private readonly BoundNode _value; internal CSharpLazyConstantPatternOperation(ITypeSymbol inputType, CSharpOperationFactory operationFactory, BoundNode value, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : - base(inputType, semanticModel, syntax, isImplicit) + base(inputType, semanticModel, syntax, type: null, constantValue: default, isImplicit) { _operationFactory = operationFactory; _value = value; @@ -1525,18 +1525,20 @@ public CSharpLazyRecursivePatternOperation( declaredSymbol: boundRecursivePattern.Variable, semanticModel: semanticModel, syntax: boundRecursivePattern.Syntax, + type: null, + constantValue: default, isImplicit: boundRecursivePattern.WasCompilerGenerated) { _operationFactory = operationFactory; _boundRecursivePattern = boundRecursivePattern; } - public override ImmutableArray CreateDeconstructionSubpatterns() + protected override ImmutableArray CreateDeconstructionSubpatterns() { return _boundRecursivePattern.Deconstruction.IsDefault ? ImmutableArray.Empty : _boundRecursivePattern.Deconstruction.SelectAsArray((p, fac) => (IPatternOperation)fac.Create(p.Pattern), _operationFactory); } - public override ImmutableArray CreatePropertySubpatterns() + protected override ImmutableArray CreatePropertySubpatterns() { return _boundRecursivePattern.Properties.IsDefault ? ImmutableArray.Empty : _boundRecursivePattern.Properties.SelectAsArray((p, recursivePattern) => recursivePattern._operationFactory.CreatePropertySubpattern(p, recursivePattern.MatchedType), this); @@ -1555,18 +1557,18 @@ public CSharpLazyPropertySubpatternOperation( ITypeSymbol matchedType, SyntaxNode syntax, SemanticModel semanticModel) - : base(semanticModel, syntax, isImplicit: false) + : base(semanticModel, syntax, type: null, constantValue: default, isImplicit: false) { _subpattern = subpattern; _operationFactory = operationFactory; _matchedType = matchedType; } - public override IOperation CreateMember() + protected override IOperation CreateMember() { return _operationFactory.CreatePropertySubpatternMember(_subpattern.Symbol, _matchedType, Syntax); } - public override IPatternOperation CreatePattern() + protected override IPatternOperation CreatePattern() { return (IPatternOperation)_operationFactory.Create(_subpattern.Pattern); } @@ -1587,18 +1589,20 @@ public CSharpLazyITuplePatternOperation(CSharpOperationFactory operationFactory, declaredSymbol: null, semanticModel: semanticModel, syntax: boundITuplePattern.Syntax, + type: null, + constantValue: default, isImplicit: boundITuplePattern.WasCompilerGenerated) { _operationFactory = operationFactory; _boundITuplePattern = boundITuplePattern; } - public override ImmutableArray CreateDeconstructionSubpatterns() + protected override ImmutableArray CreateDeconstructionSubpatterns() { return _boundITuplePattern.Subpatterns.IsDefault ? ImmutableArray.Empty : _boundITuplePattern.Subpatterns.SelectAsArray((p, fac) => (IPatternOperation)fac.Create(p.Pattern), _operationFactory); } - public override ImmutableArray CreatePropertySubpatterns() + protected override ImmutableArray CreatePropertySubpatterns() { return ImmutableArray.Empty; } @@ -1656,7 +1660,7 @@ internal sealed class CSharpLazySwitchExpressionOperation : LazySwitchExpression private readonly BoundSwitchExpression _switchExpression; public CSharpLazySwitchExpressionOperation(CSharpOperationFactory operationFactory, BoundSwitchExpression boundSwitchExpression, SemanticModel semanticModel) - : base(boundSwitchExpression.Type, semanticModel, boundSwitchExpression.Syntax, boundSwitchExpression.WasCompilerGenerated) + : base(semanticModel, boundSwitchExpression.Syntax, boundSwitchExpression.Type, constantValue: default, boundSwitchExpression.WasCompilerGenerated) { _operationFactory = operationFactory; _switchExpression = boundSwitchExpression; @@ -1678,7 +1682,7 @@ internal sealed class CSharpLazySwitchExpressionArmOperation : LazySwitchExpress private readonly BoundSwitchExpressionArm _switchExpressionArm; public CSharpLazySwitchExpressionArmOperation(CSharpOperationFactory operationFactory, BoundSwitchExpressionArm boundSwitchExpressionArm, SemanticModel semanticModel) - : base(boundSwitchExpressionArm.Locals.Cast(), semanticModel, boundSwitchExpressionArm.Syntax, boundSwitchExpressionArm.WasCompilerGenerated) + : base(boundSwitchExpressionArm.Locals.Cast(), semanticModel, boundSwitchExpressionArm.Syntax, type: null, constantValue: default, boundSwitchExpressionArm.WasCompilerGenerated) { _operationFactory = operationFactory; _switchExpressionArm = boundSwitchExpressionArm; @@ -1765,7 +1769,7 @@ internal sealed class CSharpLazyMethodBodyOperation : LazyMethodBodyOperation private readonly BoundNonConstructorMethodBody _methodBody; internal CSharpLazyMethodBodyOperation(CSharpOperationFactory operationFactory, BoundNonConstructorMethodBody methodBody, SemanticModel semanticModel, SyntaxNode syntax) : - base(semanticModel, syntax) + base(semanticModel, syntax, type: null, constantValue: default, isImplicit: false) { _operationFactory = operationFactory; _methodBody = methodBody; @@ -1788,7 +1792,7 @@ internal sealed class CSharpLazyConstructorBodyOperation : LazyConstructorBodyOp private readonly BoundConstructorMethodBody _constructorMethodBody; internal CSharpLazyConstructorBodyOperation(CSharpOperationFactory operationFactory, BoundConstructorMethodBody constructorMethodBody, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax) : - base(locals, semanticModel, syntax) + base(locals, semanticModel, syntax, type: null, constantValue: default, isImplicit: false) { _operationFactory = operationFactory; _constructorMethodBody = constructorMethodBody; @@ -1834,7 +1838,7 @@ internal sealed class CSharpLazyRangeOperation : LazyRangeOperation private readonly BoundRangeExpression _rangeExpression; internal CSharpLazyRangeOperation(CSharpOperationFactory operationFactory, BoundRangeExpression rangeExpression, bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IMethodSymbol symbol, bool isImplicit) : - base(isLifted, semanticModel, syntax, type, symbol, isImplicit) + base(isLifted, symbol, semanticModel, syntax, type, constantValue: default, isImplicit) { _operationFactory = operationFactory; _rangeExpression = rangeExpression; diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/OperationTests.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/OperationTests.cs index e581d3949e4f9..db533c0abb143 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/OperationTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/OperationTests.cs @@ -160,9 +160,9 @@ private void TestGetFlowGraphInvalidArgumentCore(string argumentExceptionMessage try { IFieldInitializerOperation initializer = new FieldInitializerOperation( - ImmutableArray.Empty, ImmutableArray.Empty, - value: null, kind: OperationKind.FieldInitializer, - semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: false); + ImmutableArray.Empty, ImmutableArray.Empty, + value: null, semanticModel: null, + syntax: null, type: null, constantValue: default, isImplicit: false); initializer = Operation.SetParentOperation(initializer, parent); _ = ControlFlowGraph.Create(initializer); } @@ -178,9 +178,9 @@ private void TestGetFlowGraphInvalidArgumentCore(string argumentExceptionMessage try { IPropertyInitializerOperation initializer = new PropertyInitializerOperation( - ImmutableArray.Empty, ImmutableArray.Empty, - value: null, kind: OperationKind.PropertyInitializer, - semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: false); + ImmutableArray.Empty, ImmutableArray.Empty, + value: null, semanticModel: null, + syntax: null, type: null, constantValue: default, isImplicit: false); initializer = Operation.SetParentOperation(initializer, parent); _ = ControlFlowGraph.Create(initializer); } @@ -196,9 +196,9 @@ private void TestGetFlowGraphInvalidArgumentCore(string argumentExceptionMessage try { IParameterInitializerOperation initializer = new ParameterInitializerOperation( - ImmutableArray.Empty, parameter: null, - value: null, kind: OperationKind.ParameterInitializer, - semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: false); + parameter: null, locals: ImmutableArray.Empty, + value: null, semanticModel: null, + syntax: null, type: null, constantValue: default, isImplicit: false); initializer = Operation.SetParentOperation(initializer, parent); _ = ControlFlowGraph.Create(initializer); } diff --git a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs index 7996b41f9b41f..7e4231afd5a20 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs @@ -2,6 +2,7 @@ // < auto-generated /> using System; using System.Collections.Generic; +using System.Threading; using System.Collections.Immutable; using Microsoft.CodeAnalysis.FlowAnalysis; @@ -85,6 +86,10 @@ public interface IVariableDeclarationGroupOperation : IOperation /// public interface ISwitchOperation : IOperation { + /// + /// Locals declared within the switch operation with scope spanning across all . + /// + ImmutableArray Locals { get; } /// /// Value to be switched upon. /// @@ -97,10 +102,6 @@ public interface ISwitchOperation : IOperation /// Exit label for the switch statement. /// ILabelSymbol ExitLabel { get; } - /// - /// Locals declared within the switch operation with scope spanning across all . - /// - ImmutableArray Locals { get; } } /// /// Represents a loop operation. @@ -418,15 +419,15 @@ public interface ITryOperation : IOperation /// public interface IUsingOperation : IOperation { - /// - /// Body of the using, over which the resources of the using are maintained. - /// - IOperation Body { get; } /// /// Declaration introduced or resource held by the using. /// IOperation Resources { get; } /// + /// Body of the using, over which the resources of the using are maintained. + /// + IOperation Body { get; } + /// /// Locals declared within the with scope spanning across this entire . /// ImmutableArray Locals { get; } @@ -839,10 +840,6 @@ public interface IUnaryOperation : IOperation /// IOperation Operand { get; } /// - /// Operator method used by the operation, null if the operation does not use an operator method. - /// - IMethodSymbol OperatorMethod { get; } - /// /// if this is a 'lifted' unary operator. When there is an /// operator that is defined to work on a value type, 'lifted' operators are /// created to work on the versions of those @@ -853,6 +850,10 @@ public interface IUnaryOperation : IOperation /// if overflow checking is performed for the arithmetic operation. /// bool IsChecked { get; } + /// + /// Operator method used by the operation, null if the operation does not use an operator method. + /// + IMethodSymbol OperatorMethod { get; } } /// /// Represents an operation with two operands and a binary operator that produces a result with a non-null type. @@ -881,10 +882,6 @@ public interface IBinaryOperation : IOperation /// IOperation RightOperand { get; } /// - /// Operator method used by the operation, null if the operation does not use an operator method. - /// - IMethodSymbol OperatorMethod { get; } - /// /// if this is a 'lifted' binary operator. When there is an /// operator that is defined to work on a value type, 'lifted' operators are /// created to work on the versions of those @@ -899,6 +896,10 @@ public interface IBinaryOperation : IOperation /// if the comparison is text based for string or object comparison in VB. /// bool IsCompareText { get; } + /// + /// Operator method used by the operation, null if the operation does not use an operator method. + /// + IMethodSymbol OperatorMethod { get; } } /// /// Represents a conditional operation with: @@ -1008,6 +1009,10 @@ public interface IObjectCreationOperation : IOperation /// IMethodSymbol Constructor { get; } /// + /// Object or collection initializer, if any. + /// + IObjectOrCollectionInitializerOperation Initializer { get; } + /// /// Arguments of the object creation, excluding the instance argument. Arguments are in evaluation order. /// /// @@ -1015,10 +1020,6 @@ public interface IObjectCreationOperation : IOperation /// Default values are supplied for optional arguments missing in source. /// ImmutableArray Arguments { get; } - /// - /// Object or collection initializer, if any. - /// - IObjectOrCollectionInitializerOperation Initializer { get; } } /// /// Represents a creation of a type parameter object, i.e. new T(), where T is a type parameter with new constraint. @@ -1188,13 +1189,18 @@ public interface ISimpleAssignmentOperation : IAssignmentOperation public interface ICompoundAssignmentOperation : IAssignmentOperation { /// - /// Kind of binary operation. + /// Conversion applied to before the operation occurs. /// - BinaryOperatorKind OperatorKind { get; } + CommonConversion InConversion { get; } /// - /// Operator method used by the operation, null if the operation does not use an operator method. + /// Conversion applied to the result of the binary operation, before it is assigned back to + /// . /// - IMethodSymbol OperatorMethod { get; } + CommonConversion OutConversion { get; } + /// + /// Kind of binary operation. + /// + BinaryOperatorKind OperatorKind { get; } /// /// if this assignment contains a 'lifted' binary operation. /// @@ -1204,14 +1210,9 @@ public interface ICompoundAssignmentOperation : IAssignmentOperation /// bool IsChecked { get; } /// - /// Conversion applied to before the operation occurs. - /// - CommonConversion InConversion { get; } - /// - /// Conversion applied to the result of the binary operation, before it is assigned back to - /// . + /// Operator method used by the operation, null if the operation does not use an operator method. /// - CommonConversion OutConversion { get; } + IMethodSymbol OperatorMethod { get; } } /// /// Represents a parenthesized operation. @@ -1702,14 +1703,6 @@ public interface IIsPatternOperation : IOperation /// public interface IIncrementOrDecrementOperation : IOperation { - /// - /// Target of the assignment. - /// - IOperation Target { get; } - /// - /// Operator method used by the operation, null if the operation does not use an operator method. - /// - IMethodSymbol OperatorMethod { get; } /// /// if this is a postfix expression. if this is a prefix expression. /// @@ -1725,6 +1718,14 @@ public interface IIncrementOrDecrementOperation : IOperation /// if overflow checking is performed for the arithmetic operation. /// bool IsChecked { get; } + /// + /// Target of the assignment. + /// + IOperation Target { get; } + /// + /// Operator method used by the operation, null if the operation does not use an operator method. + /// + IMethodSymbol OperatorMethod { get; } } /// /// Represents an operation to throw an exception. @@ -2037,18 +2038,6 @@ public interface IArgumentOperation : IOperation /// public interface ICatchClauseOperation : IOperation { - /// - /// Body of the exception handler. - /// - IBlockOperation Handler { get; } - /// - /// Locals declared by the and/or clause. - /// - ImmutableArray Locals { get; } - /// - /// Type of the exception handled by the catch clause. - /// - ITypeSymbol ExceptionType { get; } /// /// Optional source for exception. This could be any of the following operation: /// 1. Declaration for the local catch variable bound to the caught exception (C# and VB) OR @@ -2058,9 +2047,21 @@ public interface ICatchClauseOperation : IOperation /// IOperation ExceptionDeclarationOrExpression { get; } /// + /// Type of the exception handled by the catch clause. + /// + ITypeSymbol ExceptionType { get; } + /// + /// Locals declared by the and/or clause. + /// + ImmutableArray Locals { get; } + /// /// Filter operation to be executed to determine whether to handle the exception. /// IOperation Filter { get; } + /// + /// Body of the exception handler. + /// + IBlockOperation Handler { get; } } /// /// Represents a switch case section with one or more case clauses to match and one or more operations to execute within the section. @@ -2759,182 +2760,4547 @@ internal interface IWithOperation : IOperation #endregion #region Implementations - internal sealed partial class BranchOperation : Operation, IBranchOperation + internal abstract partial class BaseBlockOperation : Operation, IBlockOperation { - internal BranchOperation(ILabelSymbol target, BranchKind branchKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.Branch, semanticModel, syntax, type, constantValue, isImplicit) + internal BaseBlockOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Block, semanticModel, syntax, type, constantValue, isImplicit) { - Target = target; - BranchKind = branchKind; + Locals = locals; } - public ILabelSymbol Target { get; } - public BranchKind BranchKind { get; } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitBranch(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitBranch(this, argument); - } - internal sealed partial class EmptyOperation : Operation, IEmptyOperation - { - internal EmptyOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.Empty, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitEmpty(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitEmpty(this, argument); - } - internal sealed partial class StopOperation : Operation, IStopOperation - { - internal StopOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.Stop, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitStop(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitStop(this, argument); - } - internal sealed partial class EndOperation : Operation, IEndOperation - { - internal EndOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.End, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitEnd(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitEnd(this, argument); - } - internal sealed partial class LiteralOperation : Operation, ILiteralOperation - { - internal LiteralOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.Literal, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitLiteral(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitLiteral(this, argument); + public abstract ImmutableArray Operations { get; } + public ImmutableArray Locals { get; } + public override IEnumerable Children + { + get + { + foreach (var child in Operations) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitBlock(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitBlock(this, argument); } - internal sealed partial class LocalReferenceOperation : Operation, ILocalReferenceOperation + internal sealed partial class BlockOperation : BaseBlockOperation, IBlockOperation { - internal LocalReferenceOperation(ILocalSymbol local, bool isDeclaration, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.LocalReference, semanticModel, syntax, type, constantValue, isImplicit) + internal BlockOperation(ImmutableArray operations, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit) { - Local = local; - IsDeclaration = isDeclaration; + Operations = SetParentOperation(operations, this); } - public ILocalSymbol Local { get; } - public bool IsDeclaration { get; } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitLocalReference(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitLocalReference(this, argument); + public override ImmutableArray Operations { get; } } - internal sealed partial class ParameterReferenceOperation : Operation, IParameterReferenceOperation + internal abstract partial class LazyBlockOperation : BaseBlockOperation, IBlockOperation { - internal ParameterReferenceOperation(IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.ParameterReference, semanticModel, syntax, type, constantValue, isImplicit) + private ImmutableArray _lazyOperations; + internal LazyBlockOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateOperations(); + public override ImmutableArray Operations { - Parameter = parameter; + get + { + if (_lazyOperations.IsDefault) + { + ImmutableArray operations = CreateOperations(); + SetParentOperation(operations, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyOperations, operations, default); + } + return _lazyOperations; + } } - public IParameterSymbol Parameter { get; } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitParameterReference(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitParameterReference(this, argument); } - internal sealed partial class InstanceReferenceOperation : Operation, IInstanceReferenceOperation + internal abstract partial class BaseVariableDeclarationGroupOperation : Operation, IVariableDeclarationGroupOperation { - internal InstanceReferenceOperation(InstanceReferenceKind referenceKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.InstanceReference, semanticModel, syntax, type, constantValue, isImplicit) + internal BaseVariableDeclarationGroupOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.VariableDeclarationGroup, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract ImmutableArray Declarations { get; } + public override IEnumerable Children { - ReferenceKind = referenceKind; + get + { + foreach (var child in Declarations) + { + if (child is object) yield return child; + } + } } - public InstanceReferenceKind ReferenceKind { get; } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitInstanceReference(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitInstanceReference(this, argument); + public override void Accept(OperationVisitor visitor) => visitor.VisitVariableDeclarationGroup(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitVariableDeclarationGroup(this, argument); } - internal sealed partial class ConditionalAccessInstanceOperation : Operation, IConditionalAccessInstanceOperation + internal sealed partial class VariableDeclarationGroupOperation : BaseVariableDeclarationGroupOperation, IVariableDeclarationGroupOperation { - internal ConditionalAccessInstanceOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.ConditionalAccessInstance, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitConditionalAccessInstance(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitConditionalAccessInstance(this, argument); + internal VariableDeclarationGroupOperation(ImmutableArray declarations, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Declarations = SetParentOperation(declarations, this); + } + public override ImmutableArray Declarations { get; } } - internal sealed partial class DefaultValueOperation : Operation, IDefaultValueOperation + internal abstract partial class LazyVariableDeclarationGroupOperation : BaseVariableDeclarationGroupOperation, IVariableDeclarationGroupOperation { - internal DefaultValueOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.DefaultValue, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitDefaultValue(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDefaultValue(this, argument); + private ImmutableArray _lazyDeclarations; + internal LazyVariableDeclarationGroupOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateDeclarations(); + public override ImmutableArray Declarations + { + get + { + if (_lazyDeclarations.IsDefault) + { + ImmutableArray declarations = CreateDeclarations(); + SetParentOperation(declarations, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDeclarations, declarations, default); + } + return _lazyDeclarations; + } + } } - internal sealed partial class TypeOfOperation : Operation, ITypeOfOperation + internal abstract partial class BaseSwitchOperation : Operation, ISwitchOperation { - internal TypeOfOperation(ITypeSymbol typeOperand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.TypeOf, semanticModel, syntax, type, constantValue, isImplicit) + internal BaseSwitchOperation(ImmutableArray locals, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Switch, semanticModel, syntax, type, constantValue, isImplicit) { - TypeOperand = typeOperand; + Locals = locals; + ExitLabel = exitLabel; } - public ITypeSymbol TypeOperand { get; } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitTypeOf(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitTypeOf(this, argument); + public ImmutableArray Locals { get; } + public abstract IOperation Value { get; } + public abstract ImmutableArray Cases { get; } + public ILabelSymbol ExitLabel { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + foreach (var child in Cases) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitSwitch(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitSwitch(this, argument); } - internal sealed partial class SizeOfOperation : Operation, ISizeOfOperation + internal sealed partial class SwitchOperation : BaseSwitchOperation, ISwitchOperation { - internal SizeOfOperation(ITypeSymbol typeOperand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.SizeOf, semanticModel, syntax, type, constantValue, isImplicit) + internal SwitchOperation(ImmutableArray locals, IOperation value, ImmutableArray cases, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) { - TypeOperand = typeOperand; + Value = SetParentOperation(value, this); + Cases = SetParentOperation(cases, this); } - public ITypeSymbol TypeOperand { get; } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitSizeOf(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitSizeOf(this, argument); + public override IOperation Value { get; } + public override ImmutableArray Cases { get; } } - internal sealed partial class OmittedArgumentOperation : Operation, IOmittedArgumentOperation + internal abstract partial class LazySwitchOperation : BaseSwitchOperation, ISwitchOperation { - internal OmittedArgumentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(OperationKind.OmittedArgument, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitOmittedArgument(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitOmittedArgument(this, argument); + private IOperation _lazyValue = s_unset; + private ImmutableArray _lazyCases; + internal LazySwitchOperation(ImmutableArray locals, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, exitLabel, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + protected abstract ImmutableArray CreateCases(); + public override ImmutableArray Cases + { + get + { + if (_lazyCases.IsDefault) + { + ImmutableArray cases = CreateCases(); + SetParentOperation(cases, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyCases, cases, default); + } + return _lazyCases; + } + } } - internal abstract partial class BaseCaseClauseOperation : Operation, ICaseClauseOperation + internal abstract partial class BaseLoopOperation : Operation, ILoopOperation { - protected BaseCaseClauseOperation(CaseKind caseKind, ILabelSymbol label, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + protected BaseLoopOperation(LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(kind, semanticModel, syntax, type, constantValue, isImplicit) { - CaseKind = caseKind; - Label = label; + LoopKind = loopKind; + Locals = locals; + ContinueLabel = continueLabel; + ExitLabel = exitLabel; } - public CaseKind CaseKind { get; } - public ILabelSymbol Label { get; } + public LoopKind LoopKind { get; } + public abstract IOperation Body { get; } + public ImmutableArray Locals { get; } + public ILabelSymbol ContinueLabel { get; } + public ILabelSymbol ExitLabel { get; } + } + internal abstract partial class BaseForEachLoopOperation : BaseLoopOperation, IForEachLoopOperation + { + internal BaseForEachLoopOperation(LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(loopKind, locals, continueLabel, exitLabel, OperationKind.Loop, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation LoopControlVariable { get; } + public abstract IOperation Collection { get; } + public abstract ImmutableArray NextVariables { get; } + public override IEnumerable Children + { + get + { + if (Collection is object) yield return Collection; + if (LoopControlVariable is object) yield return LoopControlVariable; + if (Body is object) yield return Body; + foreach (var child in NextVariables) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitForEachLoop(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitForEachLoop(this, argument); } - internal sealed partial class DefaultCaseClauseOperation : BaseCaseClauseOperation, IDefaultCaseClauseOperation + internal sealed partial class ForEachLoopOperation : BaseForEachLoopOperation, IForEachLoopOperation { - internal DefaultCaseClauseOperation(CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(caseKind, label, OperationKind.CaseClause, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.VisitDefaultCaseClause(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDefaultCaseClause(this, argument); + internal ForEachLoopOperation(IOperation loopControlVariable, IOperation collection, ImmutableArray nextVariables, LoopKind loopKind, IOperation body, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(loopKind, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + { + LoopControlVariable = SetParentOperation(loopControlVariable, this); + Collection = SetParentOperation(collection, this); + NextVariables = SetParentOperation(nextVariables, this); + Body = SetParentOperation(body, this); + } + public override IOperation LoopControlVariable { get; } + public override IOperation Collection { get; } + public override ImmutableArray NextVariables { get; } + public override IOperation Body { get; } + } + internal abstract partial class LazyForEachLoopOperation : BaseForEachLoopOperation, IForEachLoopOperation + { + private IOperation _lazyLoopControlVariable = s_unset; + private IOperation _lazyCollection = s_unset; + private ImmutableArray _lazyNextVariables; + private IOperation _lazyBody = s_unset; + internal LazyForEachLoopOperation(LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(loopKind, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateLoopControlVariable(); + public override IOperation LoopControlVariable + { + get + { + if (_lazyLoopControlVariable == s_unset) + { + IOperation loopControlVariable = CreateLoopControlVariable(); + SetParentOperation(loopControlVariable, this); + Interlocked.CompareExchange(ref _lazyLoopControlVariable, loopControlVariable, s_unset); + } + return _lazyLoopControlVariable; + } + } + protected abstract IOperation CreateCollection(); + public override IOperation Collection + { + get + { + if (_lazyCollection == s_unset) + { + IOperation collection = CreateCollection(); + SetParentOperation(collection, this); + Interlocked.CompareExchange(ref _lazyCollection, collection, s_unset); + } + return _lazyCollection; + } + } + protected abstract ImmutableArray CreateNextVariables(); + public override ImmutableArray NextVariables + { + get + { + if (_lazyNextVariables.IsDefault) + { + ImmutableArray nextVariables = CreateNextVariables(); + SetParentOperation(nextVariables, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyNextVariables, nextVariables, default); + } + return _lazyNextVariables; + } + } + protected abstract IOperation CreateBody(); + public override IOperation Body + { + get + { + if (_lazyBody == s_unset) + { + IOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unset); + } + return _lazyBody; + } + } } - internal abstract partial class BasePatternOperation : Operation, IPatternOperation + internal abstract partial class BaseForLoopOperation : BaseLoopOperation, IForLoopOperation { - protected BasePatternOperation(ITypeSymbol inputType, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(kind, semanticModel, syntax, type, constantValue, isImplicit) + internal BaseForLoopOperation(ImmutableArray conditionLocals, LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(loopKind, locals, continueLabel, exitLabel, OperationKind.Loop, semanticModel, syntax, type, constantValue, isImplicit) { - InputType = inputType; + ConditionLocals = conditionLocals; } - public ITypeSymbol InputType { get; } + public abstract ImmutableArray Before { get; } + public ImmutableArray ConditionLocals { get; } + public abstract IOperation Condition { get; } + public abstract ImmutableArray AtLoopBottom { get; } + public override IEnumerable Children + { + get + { + foreach (var child in Before) + { + if (child is object) yield return child; + } + if (Condition is object) yield return Condition; + if (Body is object) yield return Body; + foreach (var child in AtLoopBottom) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitForLoop(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitForLoop(this, argument); } - internal sealed partial class DeclarationPatternOperation : BasePatternOperation, IDeclarationPatternOperation + internal sealed partial class ForLoopOperation : BaseForLoopOperation, IForLoopOperation { - internal DeclarationPatternOperation(ITypeSymbol matchedType, bool matchesNull, ISymbol declaredSymbol, ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) - : base(inputType, OperationKind.DeclarationPattern, semanticModel, syntax, type, constantValue, isImplicit) + internal ForLoopOperation(ImmutableArray before, ImmutableArray conditionLocals, IOperation condition, ImmutableArray atLoopBottom, LoopKind loopKind, IOperation body, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(conditionLocals, loopKind, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) { - MatchedType = matchedType; - MatchesNull = matchesNull; - DeclaredSymbol = declaredSymbol; + Before = SetParentOperation(before, this); + Condition = SetParentOperation(condition, this); + AtLoopBottom = SetParentOperation(atLoopBottom, this); + Body = SetParentOperation(body, this); } - public ITypeSymbol MatchedType { get; } - public bool MatchesNull { get; } - public ISymbol DeclaredSymbol { get; } + public override ImmutableArray Before { get; } + public override IOperation Condition { get; } + public override ImmutableArray AtLoopBottom { get; } + public override IOperation Body { get; } + } + internal abstract partial class LazyForLoopOperation : BaseForLoopOperation, IForLoopOperation + { + private ImmutableArray _lazyBefore; + private IOperation _lazyCondition = s_unset; + private ImmutableArray _lazyAtLoopBottom; + private IOperation _lazyBody = s_unset; + internal LazyForLoopOperation(ImmutableArray conditionLocals, LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(conditionLocals, loopKind, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateBefore(); + public override ImmutableArray Before + { + get + { + if (_lazyBefore.IsDefault) + { + ImmutableArray before = CreateBefore(); + SetParentOperation(before, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyBefore, before, default); + } + return _lazyBefore; + } + } + protected abstract IOperation CreateCondition(); + public override IOperation Condition + { + get + { + if (_lazyCondition == s_unset) + { + IOperation condition = CreateCondition(); + SetParentOperation(condition, this); + Interlocked.CompareExchange(ref _lazyCondition, condition, s_unset); + } + return _lazyCondition; + } + } + protected abstract ImmutableArray CreateAtLoopBottom(); + public override ImmutableArray AtLoopBottom + { + get + { + if (_lazyAtLoopBottom.IsDefault) + { + ImmutableArray atLoopBottom = CreateAtLoopBottom(); + SetParentOperation(atLoopBottom, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyAtLoopBottom, atLoopBottom, default); + } + return _lazyAtLoopBottom; + } + } + protected abstract IOperation CreateBody(); + public override IOperation Body + { + get + { + if (_lazyBody == s_unset) + { + IOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unset); + } + return _lazyBody; + } + } + } + internal abstract partial class BaseForToLoopOperation : BaseLoopOperation, IForToLoopOperation + { + internal BaseForToLoopOperation(bool isChecked, (ILocalSymbol LoopObject, ForToLoopOperationUserDefinedInfo UserDefinedInfo) info, LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(loopKind, locals, continueLabel, exitLabel, OperationKind.Loop, semanticModel, syntax, type, constantValue, isImplicit) + { + IsChecked = isChecked; + Info = info; + } + public abstract IOperation LoopControlVariable { get; } + public abstract IOperation InitialValue { get; } + public abstract IOperation LimitValue { get; } + public abstract IOperation StepValue { get; } + public bool IsChecked { get; } + public abstract ImmutableArray NextVariables { get; } + public (ILocalSymbol LoopObject, ForToLoopOperationUserDefinedInfo UserDefinedInfo) Info { get; } + public override IEnumerable Children + { + get + { + if (LoopControlVariable is object) yield return LoopControlVariable; + if (InitialValue is object) yield return InitialValue; + if (LimitValue is object) yield return LimitValue; + if (StepValue is object) yield return StepValue; + if (Body is object) yield return Body; + foreach (var child in NextVariables) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitForToLoop(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitForToLoop(this, argument); + } + internal sealed partial class ForToLoopOperation : BaseForToLoopOperation, IForToLoopOperation + { + internal ForToLoopOperation(IOperation loopControlVariable, IOperation initialValue, IOperation limitValue, IOperation stepValue, bool isChecked, ImmutableArray nextVariables, (ILocalSymbol LoopObject, ForToLoopOperationUserDefinedInfo UserDefinedInfo) info, LoopKind loopKind, IOperation body, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isChecked, info, loopKind, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + { + LoopControlVariable = SetParentOperation(loopControlVariable, this); + InitialValue = SetParentOperation(initialValue, this); + LimitValue = SetParentOperation(limitValue, this); + StepValue = SetParentOperation(stepValue, this); + NextVariables = SetParentOperation(nextVariables, this); + Body = SetParentOperation(body, this); + } + public override IOperation LoopControlVariable { get; } + public override IOperation InitialValue { get; } + public override IOperation LimitValue { get; } + public override IOperation StepValue { get; } + public override ImmutableArray NextVariables { get; } + public override IOperation Body { get; } + } + internal abstract partial class LazyForToLoopOperation : BaseForToLoopOperation, IForToLoopOperation + { + private IOperation _lazyLoopControlVariable = s_unset; + private IOperation _lazyInitialValue = s_unset; + private IOperation _lazyLimitValue = s_unset; + private IOperation _lazyStepValue = s_unset; + private ImmutableArray _lazyNextVariables; + private IOperation _lazyBody = s_unset; + internal LazyForToLoopOperation(bool isChecked, (ILocalSymbol LoopObject, ForToLoopOperationUserDefinedInfo UserDefinedInfo) info, LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isChecked, info, loopKind, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateLoopControlVariable(); + public override IOperation LoopControlVariable + { + get + { + if (_lazyLoopControlVariable == s_unset) + { + IOperation loopControlVariable = CreateLoopControlVariable(); + SetParentOperation(loopControlVariable, this); + Interlocked.CompareExchange(ref _lazyLoopControlVariable, loopControlVariable, s_unset); + } + return _lazyLoopControlVariable; + } + } + protected abstract IOperation CreateInitialValue(); + public override IOperation InitialValue + { + get + { + if (_lazyInitialValue == s_unset) + { + IOperation initialValue = CreateInitialValue(); + SetParentOperation(initialValue, this); + Interlocked.CompareExchange(ref _lazyInitialValue, initialValue, s_unset); + } + return _lazyInitialValue; + } + } + protected abstract IOperation CreateLimitValue(); + public override IOperation LimitValue + { + get + { + if (_lazyLimitValue == s_unset) + { + IOperation limitValue = CreateLimitValue(); + SetParentOperation(limitValue, this); + Interlocked.CompareExchange(ref _lazyLimitValue, limitValue, s_unset); + } + return _lazyLimitValue; + } + } + protected abstract IOperation CreateStepValue(); + public override IOperation StepValue + { + get + { + if (_lazyStepValue == s_unset) + { + IOperation stepValue = CreateStepValue(); + SetParentOperation(stepValue, this); + Interlocked.CompareExchange(ref _lazyStepValue, stepValue, s_unset); + } + return _lazyStepValue; + } + } + protected abstract ImmutableArray CreateNextVariables(); + public override ImmutableArray NextVariables + { + get + { + if (_lazyNextVariables.IsDefault) + { + ImmutableArray nextVariables = CreateNextVariables(); + SetParentOperation(nextVariables, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyNextVariables, nextVariables, default); + } + return _lazyNextVariables; + } + } + protected abstract IOperation CreateBody(); + public override IOperation Body + { + get + { + if (_lazyBody == s_unset) + { + IOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unset); + } + return _lazyBody; + } + } + } + internal abstract partial class BaseWhileLoopOperation : BaseLoopOperation, IWhileLoopOperation + { + internal BaseWhileLoopOperation(bool conditionIsTop, bool conditionIsUntil, LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(loopKind, locals, continueLabel, exitLabel, OperationKind.Loop, semanticModel, syntax, type, constantValue, isImplicit) + { + ConditionIsTop = conditionIsTop; + ConditionIsUntil = conditionIsUntil; + } + public abstract IOperation Condition { get; } + public bool ConditionIsTop { get; } + public bool ConditionIsUntil { get; } + public abstract IOperation IgnoredCondition { get; } + public override void Accept(OperationVisitor visitor) => visitor.VisitWhileLoop(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitWhileLoop(this, argument); + } + internal sealed partial class WhileLoopOperation : BaseWhileLoopOperation, IWhileLoopOperation + { + internal WhileLoopOperation(IOperation condition, bool conditionIsTop, bool conditionIsUntil, IOperation ignoredCondition, LoopKind loopKind, IOperation body, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(conditionIsTop, conditionIsUntil, loopKind, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + { + Condition = SetParentOperation(condition, this); + IgnoredCondition = SetParentOperation(ignoredCondition, this); + Body = SetParentOperation(body, this); + } + public override IOperation Condition { get; } + public override IOperation IgnoredCondition { get; } + public override IOperation Body { get; } + } + internal abstract partial class LazyWhileLoopOperation : BaseWhileLoopOperation, IWhileLoopOperation + { + private IOperation _lazyCondition = s_unset; + private IOperation _lazyIgnoredCondition = s_unset; + private IOperation _lazyBody = s_unset; + internal LazyWhileLoopOperation(bool conditionIsTop, bool conditionIsUntil, LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(conditionIsTop, conditionIsUntil, loopKind, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateCondition(); + public override IOperation Condition + { + get + { + if (_lazyCondition == s_unset) + { + IOperation condition = CreateCondition(); + SetParentOperation(condition, this); + Interlocked.CompareExchange(ref _lazyCondition, condition, s_unset); + } + return _lazyCondition; + } + } + protected abstract IOperation CreateIgnoredCondition(); + public override IOperation IgnoredCondition + { + get + { + if (_lazyIgnoredCondition == s_unset) + { + IOperation ignoredCondition = CreateIgnoredCondition(); + SetParentOperation(ignoredCondition, this); + Interlocked.CompareExchange(ref _lazyIgnoredCondition, ignoredCondition, s_unset); + } + return _lazyIgnoredCondition; + } + } + protected abstract IOperation CreateBody(); + public override IOperation Body + { + get + { + if (_lazyBody == s_unset) + { + IOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unset); + } + return _lazyBody; + } + } + } + internal abstract partial class BaseLabeledOperation : Operation, ILabeledOperation + { + internal BaseLabeledOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Labeled, semanticModel, syntax, type, constantValue, isImplicit) + { + Label = label; + } + public ILabelSymbol Label { get; } + public abstract IOperation Operation { get; } + public override IEnumerable Children + { + get + { + if (Operation is object) yield return Operation; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitLabeled(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitLabeled(this, argument); + } + internal sealed partial class LabeledOperation : BaseLabeledOperation, ILabeledOperation + { + internal LabeledOperation(ILabelSymbol label, IOperation operation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(label, semanticModel, syntax, type, constantValue, isImplicit) + { + Operation = SetParentOperation(operation, this); + } + public override IOperation Operation { get; } + } + internal abstract partial class LazyLabeledOperation : BaseLabeledOperation, ILabeledOperation + { + private IOperation _lazyOperation = s_unset; + internal LazyLabeledOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(label, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateOperation(); + public override IOperation Operation + { + get + { + if (_lazyOperation == s_unset) + { + IOperation operation = CreateOperation(); + SetParentOperation(operation, this); + Interlocked.CompareExchange(ref _lazyOperation, operation, s_unset); + } + return _lazyOperation; + } + } + } + internal sealed partial class BranchOperation : Operation, IBranchOperation + { + internal BranchOperation(ILabelSymbol target, BranchKind branchKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Branch, semanticModel, syntax, type, constantValue, isImplicit) + { + Target = target; + BranchKind = branchKind; + } + public ILabelSymbol Target { get; } + public BranchKind BranchKind { get; } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitBranch(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitBranch(this, argument); + } + internal sealed partial class EmptyOperation : Operation, IEmptyOperation + { + internal EmptyOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Empty, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitEmpty(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitEmpty(this, argument); + } + internal abstract partial class BaseReturnOperation : Operation, IReturnOperation + { + internal BaseReturnOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation ReturnedValue { get; } + public override IEnumerable Children + { + get + { + if (ReturnedValue is object) yield return ReturnedValue; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitReturn(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitReturn(this, argument); + } + internal sealed partial class ReturnOperation : BaseReturnOperation, IReturnOperation + { + internal ReturnOperation(IOperation returnedValue, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) + { + ReturnedValue = SetParentOperation(returnedValue, this); + } + public override IOperation ReturnedValue { get; } + } + internal abstract partial class LazyReturnOperation : BaseReturnOperation, IReturnOperation + { + private IOperation _lazyReturnedValue = s_unset; + internal LazyReturnOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateReturnedValue(); + public override IOperation ReturnedValue + { + get + { + if (_lazyReturnedValue == s_unset) + { + IOperation returnedValue = CreateReturnedValue(); + SetParentOperation(returnedValue, this); + Interlocked.CompareExchange(ref _lazyReturnedValue, returnedValue, s_unset); + } + return _lazyReturnedValue; + } + } + } + internal abstract partial class BaseLockOperation : Operation, ILockOperation + { + internal BaseLockOperation(ILocalSymbol lockTakenSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Lock, semanticModel, syntax, type, constantValue, isImplicit) + { + LockTakenSymbol = lockTakenSymbol; + } + public abstract IOperation LockedValue { get; } + public abstract IOperation Body { get; } + public ILocalSymbol LockTakenSymbol { get; } + public override IEnumerable Children + { + get + { + if (LockedValue is object) yield return LockedValue; + if (Body is object) yield return Body; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitLock(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitLock(this, argument); + } + internal sealed partial class LockOperation : BaseLockOperation, ILockOperation + { + internal LockOperation(IOperation lockedValue, IOperation body, ILocalSymbol lockTakenSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(lockTakenSymbol, semanticModel, syntax, type, constantValue, isImplicit) + { + LockedValue = SetParentOperation(lockedValue, this); + Body = SetParentOperation(body, this); + } + public override IOperation LockedValue { get; } + public override IOperation Body { get; } + } + internal abstract partial class LazyLockOperation : BaseLockOperation, ILockOperation + { + private IOperation _lazyLockedValue = s_unset; + private IOperation _lazyBody = s_unset; + internal LazyLockOperation(ILocalSymbol lockTakenSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(lockTakenSymbol, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateLockedValue(); + public override IOperation LockedValue + { + get + { + if (_lazyLockedValue == s_unset) + { + IOperation lockedValue = CreateLockedValue(); + SetParentOperation(lockedValue, this); + Interlocked.CompareExchange(ref _lazyLockedValue, lockedValue, s_unset); + } + return _lazyLockedValue; + } + } + protected abstract IOperation CreateBody(); + public override IOperation Body + { + get + { + if (_lazyBody == s_unset) + { + IOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unset); + } + return _lazyBody; + } + } + } + internal abstract partial class BaseTryOperation : Operation, ITryOperation + { + internal BaseTryOperation(ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Try, semanticModel, syntax, type, constantValue, isImplicit) + { + ExitLabel = exitLabel; + } + public abstract IBlockOperation Body { get; } + public abstract ImmutableArray Catches { get; } + public abstract IBlockOperation Finally { get; } + public ILabelSymbol ExitLabel { get; } + public override IEnumerable Children + { + get + { + if (Body is object) yield return Body; + foreach (var child in Catches) + { + if (child is object) yield return child; + } + if (Finally is object) yield return Finally; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitTry(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitTry(this, argument); + } + internal sealed partial class TryOperation : BaseTryOperation, ITryOperation + { + internal TryOperation(IBlockOperation body, ImmutableArray catches, IBlockOperation @finally, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + { + Body = SetParentOperation(body, this); + Catches = SetParentOperation(catches, this); + Finally = SetParentOperation(@finally, this); + } + public override IBlockOperation Body { get; } + public override ImmutableArray Catches { get; } + public override IBlockOperation Finally { get; } + } + internal abstract partial class LazyTryOperation : BaseTryOperation, ITryOperation + { + private IBlockOperation _lazyBody = s_unsetBlock; + private ImmutableArray _lazyCatches; + private IBlockOperation _lazyFinally = s_unsetBlock; + internal LazyTryOperation(ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(exitLabel, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IBlockOperation CreateBody(); + public override IBlockOperation Body + { + get + { + if (_lazyBody == s_unsetBlock) + { + IBlockOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unsetBlock); + } + return _lazyBody; + } + } + protected abstract ImmutableArray CreateCatches(); + public override ImmutableArray Catches + { + get + { + if (_lazyCatches.IsDefault) + { + ImmutableArray catches = CreateCatches(); + SetParentOperation(catches, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyCatches, catches, default); + } + return _lazyCatches; + } + } + protected abstract IBlockOperation CreateFinally(); + public override IBlockOperation Finally + { + get + { + if (_lazyFinally == s_unsetBlock) + { + IBlockOperation @finally = CreateFinally(); + SetParentOperation(@finally, this); + Interlocked.CompareExchange(ref _lazyFinally, @finally, s_unsetBlock); + } + return _lazyFinally; + } + } + } + internal abstract partial class BaseUsingOperation : Operation, IUsingOperation + { + internal BaseUsingOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Using, semanticModel, syntax, type, constantValue, isImplicit) + { + Locals = locals; + } + public abstract IOperation Resources { get; } + public abstract IOperation Body { get; } + public ImmutableArray Locals { get; } + public override IEnumerable Children + { + get + { + if (Resources is object) yield return Resources; + if (Body is object) yield return Body; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitUsing(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitUsing(this, argument); + } + internal sealed partial class UsingOperation : BaseUsingOperation, IUsingOperation + { + internal UsingOperation(IOperation resources, IOperation body, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit) + { + Resources = SetParentOperation(resources, this); + Body = SetParentOperation(body, this); + } + public override IOperation Resources { get; } + public override IOperation Body { get; } + } + internal abstract partial class LazyUsingOperation : BaseUsingOperation, IUsingOperation + { + private IOperation _lazyResources = s_unset; + private IOperation _lazyBody = s_unset; + internal LazyUsingOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateResources(); + public override IOperation Resources + { + get + { + if (_lazyResources == s_unset) + { + IOperation resources = CreateResources(); + SetParentOperation(resources, this); + Interlocked.CompareExchange(ref _lazyResources, resources, s_unset); + } + return _lazyResources; + } + } + protected abstract IOperation CreateBody(); + public override IOperation Body + { + get + { + if (_lazyBody == s_unset) + { + IOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unset); + } + return _lazyBody; + } + } + } + internal abstract partial class BaseExpressionStatementOperation : Operation, IExpressionStatementOperation + { + internal BaseExpressionStatementOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ExpressionStatement, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Operation { get; } + public override IEnumerable Children + { + get + { + if (Operation is object) yield return Operation; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitExpressionStatement(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitExpressionStatement(this, argument); + } + internal sealed partial class ExpressionStatementOperation : BaseExpressionStatementOperation, IExpressionStatementOperation + { + internal ExpressionStatementOperation(IOperation operation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Operation = SetParentOperation(operation, this); + } + public override IOperation Operation { get; } + } + internal abstract partial class LazyExpressionStatementOperation : BaseExpressionStatementOperation, IExpressionStatementOperation + { + private IOperation _lazyOperation = s_unset; + internal LazyExpressionStatementOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateOperation(); + public override IOperation Operation + { + get + { + if (_lazyOperation == s_unset) + { + IOperation operation = CreateOperation(); + SetParentOperation(operation, this); + Interlocked.CompareExchange(ref _lazyOperation, operation, s_unset); + } + return _lazyOperation; + } + } + } + internal abstract partial class BaseLocalFunctionOperation : Operation, ILocalFunctionOperation + { + internal BaseLocalFunctionOperation(IMethodSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.LocalFunction, semanticModel, syntax, type, constantValue, isImplicit) + { + Symbol = symbol; + } + public IMethodSymbol Symbol { get; } + public abstract IBlockOperation Body { get; } + public abstract IBlockOperation IgnoredBody { get; } + public override IEnumerable Children + { + get + { + if (Body is object) yield return Body; + if (IgnoredBody is object) yield return IgnoredBody; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitLocalFunction(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitLocalFunction(this, argument); + } + internal sealed partial class LocalFunctionOperation : BaseLocalFunctionOperation, ILocalFunctionOperation + { + internal LocalFunctionOperation(IMethodSymbol symbol, IBlockOperation body, IBlockOperation ignoredBody, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(symbol, semanticModel, syntax, type, constantValue, isImplicit) + { + Body = SetParentOperation(body, this); + IgnoredBody = SetParentOperation(ignoredBody, this); + } + public override IBlockOperation Body { get; } + public override IBlockOperation IgnoredBody { get; } + } + internal abstract partial class LazyLocalFunctionOperation : BaseLocalFunctionOperation, ILocalFunctionOperation + { + private IBlockOperation _lazyBody = s_unsetBlock; + private IBlockOperation _lazyIgnoredBody = s_unsetBlock; + internal LazyLocalFunctionOperation(IMethodSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(symbol, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IBlockOperation CreateBody(); + public override IBlockOperation Body + { + get + { + if (_lazyBody == s_unsetBlock) + { + IBlockOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unsetBlock); + } + return _lazyBody; + } + } + protected abstract IBlockOperation CreateIgnoredBody(); + public override IBlockOperation IgnoredBody + { + get + { + if (_lazyIgnoredBody == s_unsetBlock) + { + IBlockOperation ignoredBody = CreateIgnoredBody(); + SetParentOperation(ignoredBody, this); + Interlocked.CompareExchange(ref _lazyIgnoredBody, ignoredBody, s_unsetBlock); + } + return _lazyIgnoredBody; + } + } + } + internal sealed partial class StopOperation : Operation, IStopOperation + { + internal StopOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Stop, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitStop(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitStop(this, argument); + } + internal sealed partial class EndOperation : Operation, IEndOperation + { + internal EndOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.End, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitEnd(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitEnd(this, argument); + } + internal abstract partial class BaseRaiseEventOperation : Operation, IRaiseEventOperation + { + internal BaseRaiseEventOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.RaiseEvent, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IEventReferenceOperation EventReference { get; } + public abstract ImmutableArray Arguments { get; } + public override IEnumerable Children + { + get + { + if (EventReference is object) yield return EventReference; + foreach (var child in Arguments) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitRaiseEvent(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitRaiseEvent(this, argument); + } + internal sealed partial class RaiseEventOperation : BaseRaiseEventOperation, IRaiseEventOperation + { + internal RaiseEventOperation(IEventReferenceOperation eventReference, ImmutableArray arguments, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + EventReference = SetParentOperation(eventReference, this); + Arguments = SetParentOperation(arguments, this); + } + public override IEventReferenceOperation EventReference { get; } + public override ImmutableArray Arguments { get; } + } + internal abstract partial class LazyRaiseEventOperation : BaseRaiseEventOperation, IRaiseEventOperation + { + private IEventReferenceOperation _lazyEventReference = s_unsetEventReference; + private ImmutableArray _lazyArguments; + internal LazyRaiseEventOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IEventReferenceOperation CreateEventReference(); + public override IEventReferenceOperation EventReference + { + get + { + if (_lazyEventReference == s_unsetEventReference) + { + IEventReferenceOperation eventReference = CreateEventReference(); + SetParentOperation(eventReference, this); + Interlocked.CompareExchange(ref _lazyEventReference, eventReference, s_unsetEventReference); + } + return _lazyEventReference; + } + } + protected abstract ImmutableArray CreateArguments(); + public override ImmutableArray Arguments + { + get + { + if (_lazyArguments.IsDefault) + { + ImmutableArray arguments = CreateArguments(); + SetParentOperation(arguments, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArguments, arguments, default); + } + return _lazyArguments; + } + } + } + internal sealed partial class LiteralOperation : Operation, ILiteralOperation + { + internal LiteralOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Literal, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitLiteral(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitLiteral(this, argument); + } + internal abstract partial class BaseConversionOperation : Operation, IConversionOperation + { + internal BaseConversionOperation(IConvertibleConversion conversion, bool isTryCast, bool isChecked, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Conversion, semanticModel, syntax, type, constantValue, isImplicit) + { + ConversionConvertible = conversion; + IsTryCast = isTryCast; + IsChecked = isChecked; + } + public abstract IOperation Operand { get; } + internal IConvertibleConversion ConversionConvertible { get; } + public CommonConversion Conversion => ConversionConvertible.ToCommonConversion(); + public bool IsTryCast { get; } + public bool IsChecked { get; } + public override IEnumerable Children + { + get + { + if (Operand is object) yield return Operand; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitConversion(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitConversion(this, argument); + } + internal sealed partial class ConversionOperation : BaseConversionOperation, IConversionOperation + { + internal ConversionOperation(IOperation operand, IConvertibleConversion conversion, bool isTryCast, bool isChecked, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(conversion, isTryCast, isChecked, semanticModel, syntax, type, constantValue, isImplicit) + { + Operand = SetParentOperation(operand, this); + } + public override IOperation Operand { get; } + } + internal abstract partial class LazyConversionOperation : BaseConversionOperation, IConversionOperation + { + private IOperation _lazyOperand = s_unset; + internal LazyConversionOperation(IConvertibleConversion conversion, bool isTryCast, bool isChecked, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(conversion, isTryCast, isChecked, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateOperand(); + public override IOperation Operand + { + get + { + if (_lazyOperand == s_unset) + { + IOperation operand = CreateOperand(); + SetParentOperation(operand, this); + Interlocked.CompareExchange(ref _lazyOperand, operand, s_unset); + } + return _lazyOperand; + } + } + } + internal abstract partial class BaseInvocationOperation : Operation, IInvocationOperation + { + internal BaseInvocationOperation(IMethodSymbol targetMethod, bool isVirtual, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Invocation, semanticModel, syntax, type, constantValue, isImplicit) + { + TargetMethod = targetMethod; + IsVirtual = isVirtual; + } + public IMethodSymbol TargetMethod { get; } + public abstract IOperation Instance { get; } + public bool IsVirtual { get; } + public abstract ImmutableArray Arguments { get; } + public override IEnumerable Children + { + get + { + if (Instance is object) yield return Instance; + foreach (var child in Arguments) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitInvocation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitInvocation(this, argument); + } + internal sealed partial class InvocationOperation : BaseInvocationOperation, IInvocationOperation + { + internal InvocationOperation(IMethodSymbol targetMethod, IOperation instance, bool isVirtual, ImmutableArray arguments, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(targetMethod, isVirtual, semanticModel, syntax, type, constantValue, isImplicit) + { + Instance = SetParentOperation(instance, this); + Arguments = SetParentOperation(arguments, this); + } + public override IOperation Instance { get; } + public override ImmutableArray Arguments { get; } + } + internal abstract partial class LazyInvocationOperation : BaseInvocationOperation, IInvocationOperation + { + private IOperation _lazyInstance = s_unset; + private ImmutableArray _lazyArguments; + internal LazyInvocationOperation(IMethodSymbol targetMethod, bool isVirtual, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(targetMethod, isVirtual, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateInstance(); + public override IOperation Instance + { + get + { + if (_lazyInstance == s_unset) + { + IOperation instance = CreateInstance(); + SetParentOperation(instance, this); + Interlocked.CompareExchange(ref _lazyInstance, instance, s_unset); + } + return _lazyInstance; + } + } + protected abstract ImmutableArray CreateArguments(); + public override ImmutableArray Arguments + { + get + { + if (_lazyArguments.IsDefault) + { + ImmutableArray arguments = CreateArguments(); + SetParentOperation(arguments, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArguments, arguments, default); + } + return _lazyArguments; + } + } + } + internal abstract partial class BaseArrayElementReferenceOperation : Operation, IArrayElementReferenceOperation + { + internal BaseArrayElementReferenceOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ArrayElementReference, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation ArrayReference { get; } + public abstract ImmutableArray Indices { get; } + public override IEnumerable Children + { + get + { + if (ArrayReference is object) yield return ArrayReference; + foreach (var child in Indices) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitArrayElementReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitArrayElementReference(this, argument); + } + internal sealed partial class ArrayElementReferenceOperation : BaseArrayElementReferenceOperation, IArrayElementReferenceOperation + { + internal ArrayElementReferenceOperation(IOperation arrayReference, ImmutableArray indices, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + ArrayReference = SetParentOperation(arrayReference, this); + Indices = SetParentOperation(indices, this); + } + public override IOperation ArrayReference { get; } + public override ImmutableArray Indices { get; } + } + internal abstract partial class LazyArrayElementReferenceOperation : BaseArrayElementReferenceOperation, IArrayElementReferenceOperation + { + private IOperation _lazyArrayReference = s_unset; + private ImmutableArray _lazyIndices; + internal LazyArrayElementReferenceOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateArrayReference(); + public override IOperation ArrayReference + { + get + { + if (_lazyArrayReference == s_unset) + { + IOperation arrayReference = CreateArrayReference(); + SetParentOperation(arrayReference, this); + Interlocked.CompareExchange(ref _lazyArrayReference, arrayReference, s_unset); + } + return _lazyArrayReference; + } + } + protected abstract ImmutableArray CreateIndices(); + public override ImmutableArray Indices + { + get + { + if (_lazyIndices.IsDefault) + { + ImmutableArray indices = CreateIndices(); + SetParentOperation(indices, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyIndices, indices, default); + } + return _lazyIndices; + } + } + } + internal sealed partial class LocalReferenceOperation : Operation, ILocalReferenceOperation + { + internal LocalReferenceOperation(ILocalSymbol local, bool isDeclaration, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.LocalReference, semanticModel, syntax, type, constantValue, isImplicit) + { + Local = local; + IsDeclaration = isDeclaration; + } + public ILocalSymbol Local { get; } + public bool IsDeclaration { get; } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitLocalReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitLocalReference(this, argument); + } + internal sealed partial class ParameterReferenceOperation : Operation, IParameterReferenceOperation + { + internal ParameterReferenceOperation(IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ParameterReference, semanticModel, syntax, type, constantValue, isImplicit) + { + Parameter = parameter; + } + public IParameterSymbol Parameter { get; } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitParameterReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitParameterReference(this, argument); + } + internal abstract partial class BaseMemberReferenceOperation : Operation, IMemberReferenceOperation + { + protected BaseMemberReferenceOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Instance { get; } + } + internal abstract partial class BaseFieldReferenceOperation : BaseMemberReferenceOperation, IFieldReferenceOperation + { + internal BaseFieldReferenceOperation(IFieldSymbol field, bool isDeclaration, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.FieldReference, semanticModel, syntax, type, constantValue, isImplicit) + { + Field = field; + IsDeclaration = isDeclaration; + } + public IFieldSymbol Field { get; } + public bool IsDeclaration { get; } + public override IEnumerable Children + { + get + { + if (Instance is object) yield return Instance; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitFieldReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitFieldReference(this, argument); + } + internal sealed partial class FieldReferenceOperation : BaseFieldReferenceOperation, IFieldReferenceOperation + { + internal FieldReferenceOperation(IFieldSymbol field, bool isDeclaration, IOperation instance, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(field, isDeclaration, semanticModel, syntax, type, constantValue, isImplicit) + { + Instance = SetParentOperation(instance, this); + } + public override IOperation Instance { get; } + } + internal abstract partial class LazyFieldReferenceOperation : BaseFieldReferenceOperation, IFieldReferenceOperation + { + private IOperation _lazyInstance = s_unset; + internal LazyFieldReferenceOperation(IFieldSymbol field, bool isDeclaration, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(field, isDeclaration, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateInstance(); + public override IOperation Instance + { + get + { + if (_lazyInstance == s_unset) + { + IOperation instance = CreateInstance(); + SetParentOperation(instance, this); + Interlocked.CompareExchange(ref _lazyInstance, instance, s_unset); + } + return _lazyInstance; + } + } + } + internal abstract partial class BaseMethodReferenceOperation : BaseMemberReferenceOperation, IMethodReferenceOperation + { + internal BaseMethodReferenceOperation(IMethodSymbol method, bool isVirtual, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.MethodReference, semanticModel, syntax, type, constantValue, isImplicit) + { + Method = method; + IsVirtual = isVirtual; + } + public IMethodSymbol Method { get; } + public bool IsVirtual { get; } + public override IEnumerable Children + { + get + { + if (Instance is object) yield return Instance; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitMethodReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitMethodReference(this, argument); + } + internal sealed partial class MethodReferenceOperation : BaseMethodReferenceOperation, IMethodReferenceOperation + { + internal MethodReferenceOperation(IMethodSymbol method, bool isVirtual, IOperation instance, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(method, isVirtual, semanticModel, syntax, type, constantValue, isImplicit) + { + Instance = SetParentOperation(instance, this); + } + public override IOperation Instance { get; } + } + internal abstract partial class LazyMethodReferenceOperation : BaseMethodReferenceOperation, IMethodReferenceOperation + { + private IOperation _lazyInstance = s_unset; + internal LazyMethodReferenceOperation(IMethodSymbol method, bool isVirtual, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(method, isVirtual, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateInstance(); + public override IOperation Instance + { + get + { + if (_lazyInstance == s_unset) + { + IOperation instance = CreateInstance(); + SetParentOperation(instance, this); + Interlocked.CompareExchange(ref _lazyInstance, instance, s_unset); + } + return _lazyInstance; + } + } + } + internal abstract partial class BasePropertyReferenceOperation : BaseMemberReferenceOperation, IPropertyReferenceOperation + { + internal BasePropertyReferenceOperation(IPropertySymbol property, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.PropertyReference, semanticModel, syntax, type, constantValue, isImplicit) + { + Property = property; + } + public IPropertySymbol Property { get; } + public abstract ImmutableArray Arguments { get; } + public override IEnumerable Children + { + get + { + if (Instance is object) yield return Instance; + foreach (var child in Arguments) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitPropertyReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitPropertyReference(this, argument); + } + internal sealed partial class PropertyReferenceOperation : BasePropertyReferenceOperation, IPropertyReferenceOperation + { + internal PropertyReferenceOperation(IPropertySymbol property, ImmutableArray arguments, IOperation instance, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(property, semanticModel, syntax, type, constantValue, isImplicit) + { + Arguments = SetParentOperation(arguments, this); + Instance = SetParentOperation(instance, this); + } + public override ImmutableArray Arguments { get; } + public override IOperation Instance { get; } + } + internal abstract partial class LazyPropertyReferenceOperation : BasePropertyReferenceOperation, IPropertyReferenceOperation + { + private ImmutableArray _lazyArguments; + private IOperation _lazyInstance = s_unset; + internal LazyPropertyReferenceOperation(IPropertySymbol property, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(property, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateArguments(); + public override ImmutableArray Arguments + { + get + { + if (_lazyArguments.IsDefault) + { + ImmutableArray arguments = CreateArguments(); + SetParentOperation(arguments, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArguments, arguments, default); + } + return _lazyArguments; + } + } + protected abstract IOperation CreateInstance(); + public override IOperation Instance + { + get + { + if (_lazyInstance == s_unset) + { + IOperation instance = CreateInstance(); + SetParentOperation(instance, this); + Interlocked.CompareExchange(ref _lazyInstance, instance, s_unset); + } + return _lazyInstance; + } + } + } + internal abstract partial class BaseEventReferenceOperation : BaseMemberReferenceOperation, IEventReferenceOperation + { + internal BaseEventReferenceOperation(IEventSymbol @event, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.EventReference, semanticModel, syntax, type, constantValue, isImplicit) + { + Event = @event; + } + public IEventSymbol Event { get; } + public override IEnumerable Children + { + get + { + if (Instance is object) yield return Instance; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitEventReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitEventReference(this, argument); + } + internal sealed partial class EventReferenceOperation : BaseEventReferenceOperation, IEventReferenceOperation + { + internal EventReferenceOperation(IEventSymbol @event, IOperation instance, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(@event, semanticModel, syntax, type, constantValue, isImplicit) + { + Instance = SetParentOperation(instance, this); + } + public override IOperation Instance { get; } + } + internal abstract partial class LazyEventReferenceOperation : BaseEventReferenceOperation, IEventReferenceOperation + { + private IOperation _lazyInstance = s_unset; + internal LazyEventReferenceOperation(IEventSymbol @event, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(@event, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateInstance(); + public override IOperation Instance + { + get + { + if (_lazyInstance == s_unset) + { + IOperation instance = CreateInstance(); + SetParentOperation(instance, this); + Interlocked.CompareExchange(ref _lazyInstance, instance, s_unset); + } + return _lazyInstance; + } + } + } + internal abstract partial class BaseUnaryOperation : Operation, IUnaryOperation + { + internal BaseUnaryOperation(UnaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Unary, semanticModel, syntax, type, constantValue, isImplicit) + { + OperatorKind = operatorKind; + IsLifted = isLifted; + IsChecked = isChecked; + OperatorMethod = operatorMethod; + } + public UnaryOperatorKind OperatorKind { get; } + public abstract IOperation Operand { get; } + public bool IsLifted { get; } + public bool IsChecked { get; } + public IMethodSymbol OperatorMethod { get; } + public override IEnumerable Children + { + get + { + if (Operand is object) yield return Operand; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitUnaryOperator(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitUnaryOperator(this, argument); + } + internal sealed partial class UnaryOperation : BaseUnaryOperation, IUnaryOperation + { + internal UnaryOperation(UnaryOperatorKind operatorKind, IOperation operand, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) + { + Operand = SetParentOperation(operand, this); + } + public override IOperation Operand { get; } + } + internal abstract partial class LazyUnaryOperation : BaseUnaryOperation, IUnaryOperation + { + private IOperation _lazyOperand = s_unset; + internal LazyUnaryOperation(UnaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateOperand(); + public override IOperation Operand + { + get + { + if (_lazyOperand == s_unset) + { + IOperation operand = CreateOperand(); + SetParentOperation(operand, this); + Interlocked.CompareExchange(ref _lazyOperand, operand, s_unset); + } + return _lazyOperand; + } + } + } + internal abstract partial class BaseBinaryOperation : Operation, IBinaryOperation + { + internal BaseBinaryOperation(BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, bool isCompareText, IMethodSymbol operatorMethod, IMethodSymbol unaryOperatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Binary, semanticModel, syntax, type, constantValue, isImplicit) + { + OperatorKind = operatorKind; + IsLifted = isLifted; + IsChecked = isChecked; + IsCompareText = isCompareText; + OperatorMethod = operatorMethod; + UnaryOperatorMethod = unaryOperatorMethod; + } + public BinaryOperatorKind OperatorKind { get; } + public abstract IOperation LeftOperand { get; } + public abstract IOperation RightOperand { get; } + public bool IsLifted { get; } + public bool IsChecked { get; } + public bool IsCompareText { get; } + public IMethodSymbol OperatorMethod { get; } + public IMethodSymbol UnaryOperatorMethod { get; } + public override IEnumerable Children + { + get + { + if (LeftOperand is object) yield return LeftOperand; + if (RightOperand is object) yield return RightOperand; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitBinaryOperator(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitBinaryOperator(this, argument); + } + internal sealed partial class BinaryOperation : BaseBinaryOperation, IBinaryOperation + { + internal BinaryOperation(BinaryOperatorKind operatorKind, IOperation leftOperand, IOperation rightOperand, bool isLifted, bool isChecked, bool isCompareText, IMethodSymbol operatorMethod, IMethodSymbol unaryOperatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(operatorKind, isLifted, isChecked, isCompareText, operatorMethod, unaryOperatorMethod, semanticModel, syntax, type, constantValue, isImplicit) + { + LeftOperand = SetParentOperation(leftOperand, this); + RightOperand = SetParentOperation(rightOperand, this); + } + public override IOperation LeftOperand { get; } + public override IOperation RightOperand { get; } + } + internal abstract partial class LazyBinaryOperation : BaseBinaryOperation, IBinaryOperation + { + private IOperation _lazyLeftOperand = s_unset; + private IOperation _lazyRightOperand = s_unset; + internal LazyBinaryOperation(BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, bool isCompareText, IMethodSymbol operatorMethod, IMethodSymbol unaryOperatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(operatorKind, isLifted, isChecked, isCompareText, operatorMethod, unaryOperatorMethod, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateLeftOperand(); + public override IOperation LeftOperand + { + get + { + if (_lazyLeftOperand == s_unset) + { + IOperation leftOperand = CreateLeftOperand(); + SetParentOperation(leftOperand, this); + Interlocked.CompareExchange(ref _lazyLeftOperand, leftOperand, s_unset); + } + return _lazyLeftOperand; + } + } + protected abstract IOperation CreateRightOperand(); + public override IOperation RightOperand + { + get + { + if (_lazyRightOperand == s_unset) + { + IOperation rightOperand = CreateRightOperand(); + SetParentOperation(rightOperand, this); + Interlocked.CompareExchange(ref _lazyRightOperand, rightOperand, s_unset); + } + return _lazyRightOperand; + } + } + } + internal abstract partial class BaseConditionalOperation : Operation, IConditionalOperation + { + internal BaseConditionalOperation(bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Conditional, semanticModel, syntax, type, constantValue, isImplicit) + { + IsRef = isRef; + } + public abstract IOperation Condition { get; } + public abstract IOperation WhenTrue { get; } + public abstract IOperation WhenFalse { get; } + public bool IsRef { get; } + public override IEnumerable Children + { + get + { + if (Condition is object) yield return Condition; + if (WhenTrue is object) yield return WhenTrue; + if (WhenFalse is object) yield return WhenFalse; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitConditional(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitConditional(this, argument); + } + internal sealed partial class ConditionalOperation : BaseConditionalOperation, IConditionalOperation + { + internal ConditionalOperation(IOperation condition, IOperation whenTrue, IOperation whenFalse, bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isRef, semanticModel, syntax, type, constantValue, isImplicit) + { + Condition = SetParentOperation(condition, this); + WhenTrue = SetParentOperation(whenTrue, this); + WhenFalse = SetParentOperation(whenFalse, this); + } + public override IOperation Condition { get; } + public override IOperation WhenTrue { get; } + public override IOperation WhenFalse { get; } + } + internal abstract partial class LazyConditionalOperation : BaseConditionalOperation, IConditionalOperation + { + private IOperation _lazyCondition = s_unset; + private IOperation _lazyWhenTrue = s_unset; + private IOperation _lazyWhenFalse = s_unset; + internal LazyConditionalOperation(bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isRef, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateCondition(); + public override IOperation Condition + { + get + { + if (_lazyCondition == s_unset) + { + IOperation condition = CreateCondition(); + SetParentOperation(condition, this); + Interlocked.CompareExchange(ref _lazyCondition, condition, s_unset); + } + return _lazyCondition; + } + } + protected abstract IOperation CreateWhenTrue(); + public override IOperation WhenTrue + { + get + { + if (_lazyWhenTrue == s_unset) + { + IOperation whenTrue = CreateWhenTrue(); + SetParentOperation(whenTrue, this); + Interlocked.CompareExchange(ref _lazyWhenTrue, whenTrue, s_unset); + } + return _lazyWhenTrue; + } + } + protected abstract IOperation CreateWhenFalse(); + public override IOperation WhenFalse + { + get + { + if (_lazyWhenFalse == s_unset) + { + IOperation whenFalse = CreateWhenFalse(); + SetParentOperation(whenFalse, this); + Interlocked.CompareExchange(ref _lazyWhenFalse, whenFalse, s_unset); + } + return _lazyWhenFalse; + } + } + } + internal abstract partial class BaseCoalesceOperation : Operation, ICoalesceOperation + { + internal BaseCoalesceOperation(IConvertibleConversion valueConversion, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Coalesce, semanticModel, syntax, type, constantValue, isImplicit) + { + ValueConversionConvertible = valueConversion; + } + public abstract IOperation Value { get; } + public abstract IOperation WhenNull { get; } + internal IConvertibleConversion ValueConversionConvertible { get; } + public CommonConversion ValueConversion => ValueConversionConvertible.ToCommonConversion(); + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + if (WhenNull is object) yield return WhenNull; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitCoalesce(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitCoalesce(this, argument); + } + internal sealed partial class CoalesceOperation : BaseCoalesceOperation, ICoalesceOperation + { + internal CoalesceOperation(IOperation value, IOperation whenNull, IConvertibleConversion valueConversion, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(valueConversion, semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + WhenNull = SetParentOperation(whenNull, this); + } + public override IOperation Value { get; } + public override IOperation WhenNull { get; } + } + internal abstract partial class LazyCoalesceOperation : BaseCoalesceOperation, ICoalesceOperation + { + private IOperation _lazyValue = s_unset; + private IOperation _lazyWhenNull = s_unset; + internal LazyCoalesceOperation(IConvertibleConversion valueConversion, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(valueConversion, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + protected abstract IOperation CreateWhenNull(); + public override IOperation WhenNull + { + get + { + if (_lazyWhenNull == s_unset) + { + IOperation whenNull = CreateWhenNull(); + SetParentOperation(whenNull, this); + Interlocked.CompareExchange(ref _lazyWhenNull, whenNull, s_unset); + } + return _lazyWhenNull; + } + } + } + internal abstract partial class BaseAnonymousFunctionOperation : Operation, IAnonymousFunctionOperation + { + internal BaseAnonymousFunctionOperation(IMethodSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.AnonymousFunction, semanticModel, syntax, type, constantValue, isImplicit) + { + Symbol = symbol; + } + public IMethodSymbol Symbol { get; } + public abstract IBlockOperation Body { get; } + public override IEnumerable Children + { + get + { + if (Body is object) yield return Body; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitAnonymousFunction(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitAnonymousFunction(this, argument); + } + internal sealed partial class AnonymousFunctionOperation : BaseAnonymousFunctionOperation, IAnonymousFunctionOperation + { + internal AnonymousFunctionOperation(IMethodSymbol symbol, IBlockOperation body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(symbol, semanticModel, syntax, type, constantValue, isImplicit) + { + Body = SetParentOperation(body, this); + } + public override IBlockOperation Body { get; } + } + internal abstract partial class LazyAnonymousFunctionOperation : BaseAnonymousFunctionOperation, IAnonymousFunctionOperation + { + private IBlockOperation _lazyBody = s_unsetBlock; + internal LazyAnonymousFunctionOperation(IMethodSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(symbol, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IBlockOperation CreateBody(); + public override IBlockOperation Body + { + get + { + if (_lazyBody == s_unsetBlock) + { + IBlockOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unsetBlock); + } + return _lazyBody; + } + } + } + internal abstract partial class BaseObjectCreationOperation : Operation, IObjectCreationOperation + { + internal BaseObjectCreationOperation(IMethodSymbol constructor, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ObjectCreation, semanticModel, syntax, type, constantValue, isImplicit) + { + Constructor = constructor; + } + public IMethodSymbol Constructor { get; } + public abstract IObjectOrCollectionInitializerOperation Initializer { get; } + public abstract ImmutableArray Arguments { get; } + public override IEnumerable Children + { + get + { + foreach (var child in Arguments) + { + if (child is object) yield return child; + } + if (Initializer is object) yield return Initializer; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitObjectCreation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitObjectCreation(this, argument); + } + internal sealed partial class ObjectCreationOperation : BaseObjectCreationOperation, IObjectCreationOperation + { + internal ObjectCreationOperation(IMethodSymbol constructor, IObjectOrCollectionInitializerOperation initializer, ImmutableArray arguments, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(constructor, semanticModel, syntax, type, constantValue, isImplicit) + { + Initializer = SetParentOperation(initializer, this); + Arguments = SetParentOperation(arguments, this); + } + public override IObjectOrCollectionInitializerOperation Initializer { get; } + public override ImmutableArray Arguments { get; } + } + internal abstract partial class LazyObjectCreationOperation : BaseObjectCreationOperation, IObjectCreationOperation + { + private IObjectOrCollectionInitializerOperation _lazyInitializer = s_unsetObjectOrCollectionInitializer; + private ImmutableArray _lazyArguments; + internal LazyObjectCreationOperation(IMethodSymbol constructor, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(constructor, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); + public override IObjectOrCollectionInitializerOperation Initializer + { + get + { + if (_lazyInitializer == s_unsetObjectOrCollectionInitializer) + { + IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); + SetParentOperation(initializer, this); + Interlocked.CompareExchange(ref _lazyInitializer, initializer, s_unsetObjectOrCollectionInitializer); + } + return _lazyInitializer; + } + } + protected abstract ImmutableArray CreateArguments(); + public override ImmutableArray Arguments + { + get + { + if (_lazyArguments.IsDefault) + { + ImmutableArray arguments = CreateArguments(); + SetParentOperation(arguments, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArguments, arguments, default); + } + return _lazyArguments; + } + } + } + internal abstract partial class BaseTypeParameterObjectCreationOperation : Operation, ITypeParameterObjectCreationOperation + { + internal BaseTypeParameterObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.TypeParameterObjectCreation, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IObjectOrCollectionInitializerOperation Initializer { get; } + public override IEnumerable Children + { + get + { + if (Initializer is object) yield return Initializer; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitTypeParameterObjectCreation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitTypeParameterObjectCreation(this, argument); + } + internal sealed partial class TypeParameterObjectCreationOperation : BaseTypeParameterObjectCreationOperation, ITypeParameterObjectCreationOperation + { + internal TypeParameterObjectCreationOperation(IObjectOrCollectionInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Initializer = SetParentOperation(initializer, this); + } + public override IObjectOrCollectionInitializerOperation Initializer { get; } + } + internal abstract partial class LazyTypeParameterObjectCreationOperation : BaseTypeParameterObjectCreationOperation, ITypeParameterObjectCreationOperation + { + private IObjectOrCollectionInitializerOperation _lazyInitializer = s_unsetObjectOrCollectionInitializer; + internal LazyTypeParameterObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); + public override IObjectOrCollectionInitializerOperation Initializer + { + get + { + if (_lazyInitializer == s_unsetObjectOrCollectionInitializer) + { + IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); + SetParentOperation(initializer, this); + Interlocked.CompareExchange(ref _lazyInitializer, initializer, s_unsetObjectOrCollectionInitializer); + } + return _lazyInitializer; + } + } + } + internal abstract partial class BaseArrayCreationOperation : Operation, IArrayCreationOperation + { + internal BaseArrayCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ArrayCreation, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract ImmutableArray DimensionSizes { get; } + public abstract IArrayInitializerOperation Initializer { get; } + public override IEnumerable Children + { + get + { + foreach (var child in DimensionSizes) + { + if (child is object) yield return child; + } + if (Initializer is object) yield return Initializer; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitArrayCreation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitArrayCreation(this, argument); + } + internal sealed partial class ArrayCreationOperation : BaseArrayCreationOperation, IArrayCreationOperation + { + internal ArrayCreationOperation(ImmutableArray dimensionSizes, IArrayInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + DimensionSizes = SetParentOperation(dimensionSizes, this); + Initializer = SetParentOperation(initializer, this); + } + public override ImmutableArray DimensionSizes { get; } + public override IArrayInitializerOperation Initializer { get; } + } + internal abstract partial class LazyArrayCreationOperation : BaseArrayCreationOperation, IArrayCreationOperation + { + private ImmutableArray _lazyDimensionSizes; + private IArrayInitializerOperation _lazyInitializer = s_unsetArrayInitializer; + internal LazyArrayCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateDimensionSizes(); + public override ImmutableArray DimensionSizes + { + get + { + if (_lazyDimensionSizes.IsDefault) + { + ImmutableArray dimensionSizes = CreateDimensionSizes(); + SetParentOperation(dimensionSizes, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDimensionSizes, dimensionSizes, default); + } + return _lazyDimensionSizes; + } + } + protected abstract IArrayInitializerOperation CreateInitializer(); + public override IArrayInitializerOperation Initializer + { + get + { + if (_lazyInitializer == s_unsetArrayInitializer) + { + IArrayInitializerOperation initializer = CreateInitializer(); + SetParentOperation(initializer, this); + Interlocked.CompareExchange(ref _lazyInitializer, initializer, s_unsetArrayInitializer); + } + return _lazyInitializer; + } + } + } + internal sealed partial class InstanceReferenceOperation : Operation, IInstanceReferenceOperation + { + internal InstanceReferenceOperation(InstanceReferenceKind referenceKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.InstanceReference, semanticModel, syntax, type, constantValue, isImplicit) + { + ReferenceKind = referenceKind; + } + public InstanceReferenceKind ReferenceKind { get; } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitInstanceReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitInstanceReference(this, argument); + } + internal abstract partial class BaseIsTypeOperation : Operation, IIsTypeOperation + { + internal BaseIsTypeOperation(ITypeSymbol typeOperand, bool isNegated, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.IsType, semanticModel, syntax, type, constantValue, isImplicit) + { + TypeOperand = typeOperand; + IsNegated = isNegated; + } + public abstract IOperation ValueOperand { get; } + public ITypeSymbol TypeOperand { get; } + public bool IsNegated { get; } + public override IEnumerable Children + { + get + { + if (ValueOperand is object) yield return ValueOperand; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitIsType(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitIsType(this, argument); + } + internal sealed partial class IsTypeOperation : BaseIsTypeOperation, IIsTypeOperation + { + internal IsTypeOperation(IOperation valueOperand, ITypeSymbol typeOperand, bool isNegated, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(typeOperand, isNegated, semanticModel, syntax, type, constantValue, isImplicit) + { + ValueOperand = SetParentOperation(valueOperand, this); + } + public override IOperation ValueOperand { get; } + } + internal abstract partial class LazyIsTypeOperation : BaseIsTypeOperation, IIsTypeOperation + { + private IOperation _lazyValueOperand = s_unset; + internal LazyIsTypeOperation(ITypeSymbol typeOperand, bool isNegated, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(typeOperand, isNegated, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValueOperand(); + public override IOperation ValueOperand + { + get + { + if (_lazyValueOperand == s_unset) + { + IOperation valueOperand = CreateValueOperand(); + SetParentOperation(valueOperand, this); + Interlocked.CompareExchange(ref _lazyValueOperand, valueOperand, s_unset); + } + return _lazyValueOperand; + } + } + } + internal abstract partial class BaseAwaitOperation : Operation, IAwaitOperation + { + internal BaseAwaitOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Await, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Operation { get; } + public override IEnumerable Children + { + get + { + if (Operation is object) yield return Operation; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitAwait(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitAwait(this, argument); + } + internal sealed partial class AwaitOperation : BaseAwaitOperation, IAwaitOperation + { + internal AwaitOperation(IOperation operation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Operation = SetParentOperation(operation, this); + } + public override IOperation Operation { get; } + } + internal abstract partial class LazyAwaitOperation : BaseAwaitOperation, IAwaitOperation + { + private IOperation _lazyOperation = s_unset; + internal LazyAwaitOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateOperation(); + public override IOperation Operation + { + get + { + if (_lazyOperation == s_unset) + { + IOperation operation = CreateOperation(); + SetParentOperation(operation, this); + Interlocked.CompareExchange(ref _lazyOperation, operation, s_unset); + } + return _lazyOperation; + } + } + } + internal abstract partial class BaseAssignmentOperation : Operation, IAssignmentOperation + { + protected BaseAssignmentOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Target { get; } + public abstract IOperation Value { get; } + } + internal abstract partial class BaseSimpleAssignmentOperation : BaseAssignmentOperation, ISimpleAssignmentOperation + { + internal BaseSimpleAssignmentOperation(bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.SimpleAssignment, semanticModel, syntax, type, constantValue, isImplicit) + { + IsRef = isRef; + } + public bool IsRef { get; } + public override IEnumerable Children + { + get + { + if (Target is object) yield return Target; + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitSimpleAssignment(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitSimpleAssignment(this, argument); + } + internal sealed partial class SimpleAssignmentOperation : BaseSimpleAssignmentOperation, ISimpleAssignmentOperation + { + internal SimpleAssignmentOperation(bool isRef, IOperation target, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isRef, semanticModel, syntax, type, constantValue, isImplicit) + { + Target = SetParentOperation(target, this); + Value = SetParentOperation(value, this); + } + public override IOperation Target { get; } + public override IOperation Value { get; } + } + internal abstract partial class LazySimpleAssignmentOperation : BaseSimpleAssignmentOperation, ISimpleAssignmentOperation + { + private IOperation _lazyTarget = s_unset; + private IOperation _lazyValue = s_unset; + internal LazySimpleAssignmentOperation(bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isRef, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateTarget(); + public override IOperation Target + { + get + { + if (_lazyTarget == s_unset) + { + IOperation target = CreateTarget(); + SetParentOperation(target, this); + Interlocked.CompareExchange(ref _lazyTarget, target, s_unset); + } + return _lazyTarget; + } + } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseCompoundAssignmentOperation : BaseAssignmentOperation, ICompoundAssignmentOperation + { + internal BaseCompoundAssignmentOperation(IConvertibleConversion inConversion, IConvertibleConversion outConversion, BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.CompoundAssignment, semanticModel, syntax, type, constantValue, isImplicit) + { + InConversionConvertible = inConversion; + OutConversionConvertible = outConversion; + OperatorKind = operatorKind; + IsLifted = isLifted; + IsChecked = isChecked; + OperatorMethod = operatorMethod; + } + internal IConvertibleConversion InConversionConvertible { get; } + public CommonConversion InConversion => InConversionConvertible.ToCommonConversion(); + internal IConvertibleConversion OutConversionConvertible { get; } + public CommonConversion OutConversion => OutConversionConvertible.ToCommonConversion(); + public BinaryOperatorKind OperatorKind { get; } + public bool IsLifted { get; } + public bool IsChecked { get; } + public IMethodSymbol OperatorMethod { get; } + public override IEnumerable Children + { + get + { + if (Target is object) yield return Target; + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitCompoundAssignment(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitCompoundAssignment(this, argument); + } + internal sealed partial class CompoundAssignmentOperation : BaseCompoundAssignmentOperation, ICompoundAssignmentOperation + { + internal CompoundAssignmentOperation(IConvertibleConversion inConversion, IConvertibleConversion outConversion, BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, IOperation target, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(inConversion, outConversion, operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) + { + Target = SetParentOperation(target, this); + Value = SetParentOperation(value, this); + } + public override IOperation Target { get; } + public override IOperation Value { get; } + } + internal abstract partial class LazyCompoundAssignmentOperation : BaseCompoundAssignmentOperation, ICompoundAssignmentOperation + { + private IOperation _lazyTarget = s_unset; + private IOperation _lazyValue = s_unset; + internal LazyCompoundAssignmentOperation(IConvertibleConversion inConversion, IConvertibleConversion outConversion, BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(inConversion, outConversion, operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateTarget(); + public override IOperation Target + { + get + { + if (_lazyTarget == s_unset) + { + IOperation target = CreateTarget(); + SetParentOperation(target, this); + Interlocked.CompareExchange(ref _lazyTarget, target, s_unset); + } + return _lazyTarget; + } + } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseParenthesizedOperation : Operation, IParenthesizedOperation + { + internal BaseParenthesizedOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Parenthesized, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Operand { get; } + public override IEnumerable Children + { + get + { + if (Operand is object) yield return Operand; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitParenthesized(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitParenthesized(this, argument); + } + internal sealed partial class ParenthesizedOperation : BaseParenthesizedOperation, IParenthesizedOperation + { + internal ParenthesizedOperation(IOperation operand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Operand = SetParentOperation(operand, this); + } + public override IOperation Operand { get; } + } + internal abstract partial class LazyParenthesizedOperation : BaseParenthesizedOperation, IParenthesizedOperation + { + private IOperation _lazyOperand = s_unset; + internal LazyParenthesizedOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateOperand(); + public override IOperation Operand + { + get + { + if (_lazyOperand == s_unset) + { + IOperation operand = CreateOperand(); + SetParentOperation(operand, this); + Interlocked.CompareExchange(ref _lazyOperand, operand, s_unset); + } + return _lazyOperand; + } + } + } + internal abstract partial class BaseEventAssignmentOperation : Operation, IEventAssignmentOperation + { + internal BaseEventAssignmentOperation(bool adds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.EventAssignment, semanticModel, syntax, type, constantValue, isImplicit) + { + Adds = adds; + } + public abstract IOperation EventReference { get; } + public abstract IOperation HandlerValue { get; } + public bool Adds { get; } + public override IEnumerable Children + { + get + { + if (EventReference is object) yield return EventReference; + if (HandlerValue is object) yield return HandlerValue; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitEventAssignment(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitEventAssignment(this, argument); + } + internal sealed partial class EventAssignmentOperation : BaseEventAssignmentOperation, IEventAssignmentOperation + { + internal EventAssignmentOperation(IOperation eventReference, IOperation handlerValue, bool adds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(adds, semanticModel, syntax, type, constantValue, isImplicit) + { + EventReference = SetParentOperation(eventReference, this); + HandlerValue = SetParentOperation(handlerValue, this); + } + public override IOperation EventReference { get; } + public override IOperation HandlerValue { get; } + } + internal abstract partial class LazyEventAssignmentOperation : BaseEventAssignmentOperation, IEventAssignmentOperation + { + private IOperation _lazyEventReference = s_unset; + private IOperation _lazyHandlerValue = s_unset; + internal LazyEventAssignmentOperation(bool adds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(adds, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateEventReference(); + public override IOperation EventReference + { + get + { + if (_lazyEventReference == s_unset) + { + IOperation eventReference = CreateEventReference(); + SetParentOperation(eventReference, this); + Interlocked.CompareExchange(ref _lazyEventReference, eventReference, s_unset); + } + return _lazyEventReference; + } + } + protected abstract IOperation CreateHandlerValue(); + public override IOperation HandlerValue + { + get + { + if (_lazyHandlerValue == s_unset) + { + IOperation handlerValue = CreateHandlerValue(); + SetParentOperation(handlerValue, this); + Interlocked.CompareExchange(ref _lazyHandlerValue, handlerValue, s_unset); + } + return _lazyHandlerValue; + } + } + } + internal abstract partial class BaseConditionalAccessOperation : Operation, IConditionalAccessOperation + { + internal BaseConditionalAccessOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ConditionalAccess, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Operation { get; } + public abstract IOperation WhenNotNull { get; } + public override IEnumerable Children + { + get + { + if (Operation is object) yield return Operation; + if (WhenNotNull is object) yield return WhenNotNull; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitConditionalAccess(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitConditionalAccess(this, argument); + } + internal sealed partial class ConditionalAccessOperation : BaseConditionalAccessOperation, IConditionalAccessOperation + { + internal ConditionalAccessOperation(IOperation operation, IOperation whenNotNull, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Operation = SetParentOperation(operation, this); + WhenNotNull = SetParentOperation(whenNotNull, this); + } + public override IOperation Operation { get; } + public override IOperation WhenNotNull { get; } + } + internal abstract partial class LazyConditionalAccessOperation : BaseConditionalAccessOperation, IConditionalAccessOperation + { + private IOperation _lazyOperation = s_unset; + private IOperation _lazyWhenNotNull = s_unset; + internal LazyConditionalAccessOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateOperation(); + public override IOperation Operation + { + get + { + if (_lazyOperation == s_unset) + { + IOperation operation = CreateOperation(); + SetParentOperation(operation, this); + Interlocked.CompareExchange(ref _lazyOperation, operation, s_unset); + } + return _lazyOperation; + } + } + protected abstract IOperation CreateWhenNotNull(); + public override IOperation WhenNotNull + { + get + { + if (_lazyWhenNotNull == s_unset) + { + IOperation whenNotNull = CreateWhenNotNull(); + SetParentOperation(whenNotNull, this); + Interlocked.CompareExchange(ref _lazyWhenNotNull, whenNotNull, s_unset); + } + return _lazyWhenNotNull; + } + } + } + internal sealed partial class ConditionalAccessInstanceOperation : Operation, IConditionalAccessInstanceOperation + { + internal ConditionalAccessInstanceOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ConditionalAccessInstance, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitConditionalAccessInstance(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitConditionalAccessInstance(this, argument); + } + internal abstract partial class BaseInterpolatedStringOperation : Operation, IInterpolatedStringOperation + { + internal BaseInterpolatedStringOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.InterpolatedString, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract ImmutableArray Parts { get; } + public override IEnumerable Children + { + get + { + foreach (var child in Parts) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitInterpolatedString(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitInterpolatedString(this, argument); + } + internal sealed partial class InterpolatedStringOperation : BaseInterpolatedStringOperation, IInterpolatedStringOperation + { + internal InterpolatedStringOperation(ImmutableArray parts, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Parts = SetParentOperation(parts, this); + } + public override ImmutableArray Parts { get; } + } + internal abstract partial class LazyInterpolatedStringOperation : BaseInterpolatedStringOperation, IInterpolatedStringOperation + { + private ImmutableArray _lazyParts; + internal LazyInterpolatedStringOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateParts(); + public override ImmutableArray Parts + { + get + { + if (_lazyParts.IsDefault) + { + ImmutableArray parts = CreateParts(); + SetParentOperation(parts, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyParts, parts, default); + } + return _lazyParts; + } + } + } + internal abstract partial class BaseAnonymousObjectCreationOperation : Operation, IAnonymousObjectCreationOperation + { + internal BaseAnonymousObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.AnonymousObjectCreation, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract ImmutableArray Initializers { get; } + public override IEnumerable Children + { + get + { + foreach (var child in Initializers) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitAnonymousObjectCreation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitAnonymousObjectCreation(this, argument); + } + internal sealed partial class AnonymousObjectCreationOperation : BaseAnonymousObjectCreationOperation, IAnonymousObjectCreationOperation + { + internal AnonymousObjectCreationOperation(ImmutableArray initializers, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Initializers = SetParentOperation(initializers, this); + } + public override ImmutableArray Initializers { get; } + } + internal abstract partial class LazyAnonymousObjectCreationOperation : BaseAnonymousObjectCreationOperation, IAnonymousObjectCreationOperation + { + private ImmutableArray _lazyInitializers; + internal LazyAnonymousObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateInitializers(); + public override ImmutableArray Initializers + { + get + { + if (_lazyInitializers.IsDefault) + { + ImmutableArray initializers = CreateInitializers(); + SetParentOperation(initializers, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyInitializers, initializers, default); + } + return _lazyInitializers; + } + } + } + internal abstract partial class BaseObjectOrCollectionInitializerOperation : Operation, IObjectOrCollectionInitializerOperation + { + internal BaseObjectOrCollectionInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ObjectOrCollectionInitializer, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract ImmutableArray Initializers { get; } + public override IEnumerable Children + { + get + { + foreach (var child in Initializers) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitObjectOrCollectionInitializer(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitObjectOrCollectionInitializer(this, argument); + } + internal sealed partial class ObjectOrCollectionInitializerOperation : BaseObjectOrCollectionInitializerOperation, IObjectOrCollectionInitializerOperation + { + internal ObjectOrCollectionInitializerOperation(ImmutableArray initializers, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Initializers = SetParentOperation(initializers, this); + } + public override ImmutableArray Initializers { get; } + } + internal abstract partial class LazyObjectOrCollectionInitializerOperation : BaseObjectOrCollectionInitializerOperation, IObjectOrCollectionInitializerOperation + { + private ImmutableArray _lazyInitializers; + internal LazyObjectOrCollectionInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateInitializers(); + public override ImmutableArray Initializers + { + get + { + if (_lazyInitializers.IsDefault) + { + ImmutableArray initializers = CreateInitializers(); + SetParentOperation(initializers, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyInitializers, initializers, default); + } + return _lazyInitializers; + } + } + } + internal abstract partial class BaseMemberInitializerOperation : Operation, IMemberInitializerOperation + { + internal BaseMemberInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.MemberInitializer, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation InitializedMember { get; } + public abstract IObjectOrCollectionInitializerOperation Initializer { get; } + public override IEnumerable Children + { + get + { + if (InitializedMember is object) yield return InitializedMember; + if (Initializer is object) yield return Initializer; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitMemberInitializer(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitMemberInitializer(this, argument); + } + internal sealed partial class MemberInitializerOperation : BaseMemberInitializerOperation, IMemberInitializerOperation + { + internal MemberInitializerOperation(IOperation initializedMember, IObjectOrCollectionInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + InitializedMember = SetParentOperation(initializedMember, this); + Initializer = SetParentOperation(initializer, this); + } + public override IOperation InitializedMember { get; } + public override IObjectOrCollectionInitializerOperation Initializer { get; } + } + internal abstract partial class LazyMemberInitializerOperation : BaseMemberInitializerOperation, IMemberInitializerOperation + { + private IOperation _lazyInitializedMember = s_unset; + private IObjectOrCollectionInitializerOperation _lazyInitializer = s_unsetObjectOrCollectionInitializer; + internal LazyMemberInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateInitializedMember(); + public override IOperation InitializedMember + { + get + { + if (_lazyInitializedMember == s_unset) + { + IOperation initializedMember = CreateInitializedMember(); + SetParentOperation(initializedMember, this); + Interlocked.CompareExchange(ref _lazyInitializedMember, initializedMember, s_unset); + } + return _lazyInitializedMember; + } + } + protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); + public override IObjectOrCollectionInitializerOperation Initializer + { + get + { + if (_lazyInitializer == s_unsetObjectOrCollectionInitializer) + { + IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); + SetParentOperation(initializer, this); + Interlocked.CompareExchange(ref _lazyInitializer, initializer, s_unsetObjectOrCollectionInitializer); + } + return _lazyInitializer; + } + } + } + internal abstract partial class BaseNameOfOperation : Operation, INameOfOperation + { + internal BaseNameOfOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.NameOf, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Argument { get; } + public override IEnumerable Children + { + get + { + if (Argument is object) yield return Argument; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitNameOf(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitNameOf(this, argument); + } + internal sealed partial class NameOfOperation : BaseNameOfOperation, INameOfOperation + { + internal NameOfOperation(IOperation argument, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Argument = SetParentOperation(argument, this); + } + public override IOperation Argument { get; } + } + internal abstract partial class LazyNameOfOperation : BaseNameOfOperation, INameOfOperation + { + private IOperation _lazyArgument = s_unset; + internal LazyNameOfOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateArgument(); + public override IOperation Argument + { + get + { + if (_lazyArgument == s_unset) + { + IOperation argument = CreateArgument(); + SetParentOperation(argument, this); + Interlocked.CompareExchange(ref _lazyArgument, argument, s_unset); + } + return _lazyArgument; + } + } + } + internal abstract partial class BaseTupleOperation : Operation, ITupleOperation + { + internal BaseTupleOperation(ITypeSymbol naturalType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Tuple, semanticModel, syntax, type, constantValue, isImplicit) + { + NaturalType = naturalType; + } + public abstract ImmutableArray Elements { get; } + public ITypeSymbol NaturalType { get; } + public override IEnumerable Children + { + get + { + foreach (var child in Elements) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitTuple(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitTuple(this, argument); + } + internal sealed partial class TupleOperation : BaseTupleOperation, ITupleOperation + { + internal TupleOperation(ImmutableArray elements, ITypeSymbol naturalType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(naturalType, semanticModel, syntax, type, constantValue, isImplicit) + { + Elements = SetParentOperation(elements, this); + } + public override ImmutableArray Elements { get; } + } + internal abstract partial class LazyTupleOperation : BaseTupleOperation, ITupleOperation + { + private ImmutableArray _lazyElements; + internal LazyTupleOperation(ITypeSymbol naturalType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(naturalType, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateElements(); + public override ImmutableArray Elements + { + get + { + if (_lazyElements.IsDefault) + { + ImmutableArray elements = CreateElements(); + SetParentOperation(elements, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyElements, elements, default); + } + return _lazyElements; + } + } + } + internal abstract partial class BaseDynamicMemberReferenceOperation : Operation, IDynamicMemberReferenceOperation + { + internal BaseDynamicMemberReferenceOperation(string memberName, ImmutableArray typeArguments, ITypeSymbol containingType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.DynamicMemberReference, semanticModel, syntax, type, constantValue, isImplicit) + { + MemberName = memberName; + TypeArguments = typeArguments; + ContainingType = containingType; + } + public abstract IOperation Instance { get; } + public string MemberName { get; } + public ImmutableArray TypeArguments { get; } + public ITypeSymbol ContainingType { get; } + public override IEnumerable Children + { + get + { + if (Instance is object) yield return Instance; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitDynamicMemberReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDynamicMemberReference(this, argument); + } + internal sealed partial class DynamicMemberReferenceOperation : BaseDynamicMemberReferenceOperation, IDynamicMemberReferenceOperation + { + internal DynamicMemberReferenceOperation(IOperation instance, string memberName, ImmutableArray typeArguments, ITypeSymbol containingType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(memberName, typeArguments, containingType, semanticModel, syntax, type, constantValue, isImplicit) + { + Instance = SetParentOperation(instance, this); + } + public override IOperation Instance { get; } + } + internal abstract partial class LazyDynamicMemberReferenceOperation : BaseDynamicMemberReferenceOperation, IDynamicMemberReferenceOperation + { + private IOperation _lazyInstance = s_unset; + internal LazyDynamicMemberReferenceOperation(string memberName, ImmutableArray typeArguments, ITypeSymbol containingType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(memberName, typeArguments, containingType, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateInstance(); + public override IOperation Instance + { + get + { + if (_lazyInstance == s_unset) + { + IOperation instance = CreateInstance(); + SetParentOperation(instance, this); + Interlocked.CompareExchange(ref _lazyInstance, instance, s_unset); + } + return _lazyInstance; + } + } + } + internal abstract partial class BaseTranslatedQueryOperation : Operation, ITranslatedQueryOperation + { + internal BaseTranslatedQueryOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.TranslatedQuery, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Operation { get; } + public override IEnumerable Children + { + get + { + if (Operation is object) yield return Operation; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitTranslatedQuery(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitTranslatedQuery(this, argument); + } + internal sealed partial class TranslatedQueryOperation : BaseTranslatedQueryOperation, ITranslatedQueryOperation + { + internal TranslatedQueryOperation(IOperation operation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Operation = SetParentOperation(operation, this); + } + public override IOperation Operation { get; } + } + internal abstract partial class LazyTranslatedQueryOperation : BaseTranslatedQueryOperation, ITranslatedQueryOperation + { + private IOperation _lazyOperation = s_unset; + internal LazyTranslatedQueryOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateOperation(); + public override IOperation Operation + { + get + { + if (_lazyOperation == s_unset) + { + IOperation operation = CreateOperation(); + SetParentOperation(operation, this); + Interlocked.CompareExchange(ref _lazyOperation, operation, s_unset); + } + return _lazyOperation; + } + } + } + internal abstract partial class BaseDelegateCreationOperation : Operation, IDelegateCreationOperation + { + internal BaseDelegateCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.DelegateCreation, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Target { get; } + public override IEnumerable Children + { + get + { + if (Target is object) yield return Target; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitDelegateCreation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDelegateCreation(this, argument); + } + internal sealed partial class DelegateCreationOperation : BaseDelegateCreationOperation, IDelegateCreationOperation + { + internal DelegateCreationOperation(IOperation target, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Target = SetParentOperation(target, this); + } + public override IOperation Target { get; } + } + internal abstract partial class LazyDelegateCreationOperation : BaseDelegateCreationOperation, IDelegateCreationOperation + { + private IOperation _lazyTarget = s_unset; + internal LazyDelegateCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateTarget(); + public override IOperation Target + { + get + { + if (_lazyTarget == s_unset) + { + IOperation target = CreateTarget(); + SetParentOperation(target, this); + Interlocked.CompareExchange(ref _lazyTarget, target, s_unset); + } + return _lazyTarget; + } + } + } + internal sealed partial class DefaultValueOperation : Operation, IDefaultValueOperation + { + internal DefaultValueOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.DefaultValue, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitDefaultValue(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDefaultValue(this, argument); + } + internal sealed partial class TypeOfOperation : Operation, ITypeOfOperation + { + internal TypeOfOperation(ITypeSymbol typeOperand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.TypeOf, semanticModel, syntax, type, constantValue, isImplicit) + { + TypeOperand = typeOperand; + } + public ITypeSymbol TypeOperand { get; } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitTypeOf(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitTypeOf(this, argument); + } + internal sealed partial class SizeOfOperation : Operation, ISizeOfOperation + { + internal SizeOfOperation(ITypeSymbol typeOperand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.SizeOf, semanticModel, syntax, type, constantValue, isImplicit) + { + TypeOperand = typeOperand; + } + public ITypeSymbol TypeOperand { get; } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitSizeOf(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitSizeOf(this, argument); + } + internal abstract partial class BaseAddressOfOperation : Operation, IAddressOfOperation + { + internal BaseAddressOfOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.AddressOf, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Reference { get; } + public override IEnumerable Children + { + get + { + if (Reference is object) yield return Reference; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitAddressOf(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitAddressOf(this, argument); + } + internal sealed partial class AddressOfOperation : BaseAddressOfOperation, IAddressOfOperation + { + internal AddressOfOperation(IOperation reference, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Reference = SetParentOperation(reference, this); + } + public override IOperation Reference { get; } + } + internal abstract partial class LazyAddressOfOperation : BaseAddressOfOperation, IAddressOfOperation + { + private IOperation _lazyReference = s_unset; + internal LazyAddressOfOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateReference(); + public override IOperation Reference + { + get + { + if (_lazyReference == s_unset) + { + IOperation reference = CreateReference(); + SetParentOperation(reference, this); + Interlocked.CompareExchange(ref _lazyReference, reference, s_unset); + } + return _lazyReference; + } + } + } + internal abstract partial class BaseIsPatternOperation : Operation, IIsPatternOperation + { + internal BaseIsPatternOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.IsPattern, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Value { get; } + public abstract IPatternOperation Pattern { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + if (Pattern is object) yield return Pattern; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitIsPattern(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitIsPattern(this, argument); + } + internal sealed partial class IsPatternOperation : BaseIsPatternOperation, IIsPatternOperation + { + internal IsPatternOperation(IOperation value, IPatternOperation pattern, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + Pattern = SetParentOperation(pattern, this); + } + public override IOperation Value { get; } + public override IPatternOperation Pattern { get; } + } + internal abstract partial class LazyIsPatternOperation : BaseIsPatternOperation, IIsPatternOperation + { + private IOperation _lazyValue = s_unset; + private IPatternOperation _lazyPattern = s_unsetPattern; + internal LazyIsPatternOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + protected abstract IPatternOperation CreatePattern(); + public override IPatternOperation Pattern + { + get + { + if (_lazyPattern == s_unsetPattern) + { + IPatternOperation pattern = CreatePattern(); + SetParentOperation(pattern, this); + Interlocked.CompareExchange(ref _lazyPattern, pattern, s_unsetPattern); + } + return _lazyPattern; + } + } + } + internal abstract partial class BaseIncrementOrDecrementOperation : Operation, IIncrementOrDecrementOperation + { + internal BaseIncrementOrDecrementOperation(bool isPostfix, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) + { + IsPostfix = isPostfix; + IsLifted = isLifted; + IsChecked = isChecked; + OperatorMethod = operatorMethod; + } + public bool IsPostfix { get; } + public bool IsLifted { get; } + public bool IsChecked { get; } + public abstract IOperation Target { get; } + public IMethodSymbol OperatorMethod { get; } + public override IEnumerable Children + { + get + { + if (Target is object) yield return Target; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitIncrementOrDecrement(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitIncrementOrDecrement(this, argument); + } + internal sealed partial class IncrementOrDecrementOperation : BaseIncrementOrDecrementOperation, IIncrementOrDecrementOperation + { + internal IncrementOrDecrementOperation(bool isPostfix, bool isLifted, bool isChecked, IOperation target, IMethodSymbol operatorMethod, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isPostfix, isLifted, isChecked, operatorMethod, kind, semanticModel, syntax, type, constantValue, isImplicit) + { + Target = SetParentOperation(target, this); + } + public override IOperation Target { get; } + } + internal abstract partial class LazyIncrementOrDecrementOperation : BaseIncrementOrDecrementOperation, IIncrementOrDecrementOperation + { + private IOperation _lazyTarget = s_unset; + internal LazyIncrementOrDecrementOperation(bool isPostfix, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isPostfix, isLifted, isChecked, operatorMethod, kind, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateTarget(); + public override IOperation Target + { + get + { + if (_lazyTarget == s_unset) + { + IOperation target = CreateTarget(); + SetParentOperation(target, this); + Interlocked.CompareExchange(ref _lazyTarget, target, s_unset); + } + return _lazyTarget; + } + } + } + internal abstract partial class BaseThrowOperation : Operation, IThrowOperation + { + internal BaseThrowOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Throw, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Exception { get; } + public override IEnumerable Children + { + get + { + if (Exception is object) yield return Exception; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitThrow(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitThrow(this, argument); + } + internal sealed partial class ThrowOperation : BaseThrowOperation, IThrowOperation + { + internal ThrowOperation(IOperation exception, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Exception = SetParentOperation(exception, this); + } + public override IOperation Exception { get; } + } + internal abstract partial class LazyThrowOperation : BaseThrowOperation, IThrowOperation + { + private IOperation _lazyException = s_unset; + internal LazyThrowOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateException(); + public override IOperation Exception + { + get + { + if (_lazyException == s_unset) + { + IOperation exception = CreateException(); + SetParentOperation(exception, this); + Interlocked.CompareExchange(ref _lazyException, exception, s_unset); + } + return _lazyException; + } + } + } + internal abstract partial class BaseDeconstructionAssignmentOperation : BaseAssignmentOperation, IDeconstructionAssignmentOperation + { + internal BaseDeconstructionAssignmentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.DeconstructionAssignment, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children + { + get + { + if (Target is object) yield return Target; + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitDeconstructionAssignment(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDeconstructionAssignment(this, argument); + } + internal sealed partial class DeconstructionAssignmentOperation : BaseDeconstructionAssignmentOperation, IDeconstructionAssignmentOperation + { + internal DeconstructionAssignmentOperation(IOperation target, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Target = SetParentOperation(target, this); + Value = SetParentOperation(value, this); + } + public override IOperation Target { get; } + public override IOperation Value { get; } + } + internal abstract partial class LazyDeconstructionAssignmentOperation : BaseDeconstructionAssignmentOperation, IDeconstructionAssignmentOperation + { + private IOperation _lazyTarget = s_unset; + private IOperation _lazyValue = s_unset; + internal LazyDeconstructionAssignmentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateTarget(); + public override IOperation Target + { + get + { + if (_lazyTarget == s_unset) + { + IOperation target = CreateTarget(); + SetParentOperation(target, this); + Interlocked.CompareExchange(ref _lazyTarget, target, s_unset); + } + return _lazyTarget; + } + } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseDeclarationExpressionOperation : Operation, IDeclarationExpressionOperation + { + internal BaseDeclarationExpressionOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.DeclarationExpression, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Expression { get; } + public override IEnumerable Children + { + get + { + if (Expression is object) yield return Expression; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitDeclarationExpression(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDeclarationExpression(this, argument); + } + internal sealed partial class DeclarationExpressionOperation : BaseDeclarationExpressionOperation, IDeclarationExpressionOperation + { + internal DeclarationExpressionOperation(IOperation expression, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Expression = SetParentOperation(expression, this); + } + public override IOperation Expression { get; } + } + internal abstract partial class LazyDeclarationExpressionOperation : BaseDeclarationExpressionOperation, IDeclarationExpressionOperation + { + private IOperation _lazyExpression = s_unset; + internal LazyDeclarationExpressionOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateExpression(); + public override IOperation Expression + { + get + { + if (_lazyExpression == s_unset) + { + IOperation expression = CreateExpression(); + SetParentOperation(expression, this); + Interlocked.CompareExchange(ref _lazyExpression, expression, s_unset); + } + return _lazyExpression; + } + } + } + internal sealed partial class OmittedArgumentOperation : Operation, IOmittedArgumentOperation + { + internal OmittedArgumentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.OmittedArgument, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitOmittedArgument(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitOmittedArgument(this, argument); + } + internal abstract partial class BaseSymbolInitializerOperation : Operation, ISymbolInitializerOperation + { + protected BaseSymbolInitializerOperation(ImmutableArray locals, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) + { + Locals = locals; + } + public ImmutableArray Locals { get; } + public abstract IOperation Value { get; } + } + internal abstract partial class BaseFieldInitializerOperation : BaseSymbolInitializerOperation, IFieldInitializerOperation + { + internal BaseFieldInitializerOperation(ImmutableArray initializedFields, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, OperationKind.FieldInitializer, semanticModel, syntax, type, constantValue, isImplicit) + { + InitializedFields = initializedFields; + } + public ImmutableArray InitializedFields { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitFieldInitializer(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitFieldInitializer(this, argument); + } + internal sealed partial class FieldInitializerOperation : BaseFieldInitializerOperation, IFieldInitializerOperation + { + internal FieldInitializerOperation(ImmutableArray initializedFields, ImmutableArray locals, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(initializedFields, locals, semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + } + public override IOperation Value { get; } + } + internal abstract partial class LazyFieldInitializerOperation : BaseFieldInitializerOperation, IFieldInitializerOperation + { + private IOperation _lazyValue = s_unset; + internal LazyFieldInitializerOperation(ImmutableArray initializedFields, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(initializedFields, locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseVariableInitializerOperation : BaseSymbolInitializerOperation, IVariableInitializerOperation + { + internal BaseVariableInitializerOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, OperationKind.VariableInitializer, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitVariableInitializer(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitVariableInitializer(this, argument); + } + internal sealed partial class VariableInitializerOperation : BaseVariableInitializerOperation, IVariableInitializerOperation + { + internal VariableInitializerOperation(ImmutableArray locals, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + } + public override IOperation Value { get; } + } + internal abstract partial class LazyVariableInitializerOperation : BaseVariableInitializerOperation, IVariableInitializerOperation + { + private IOperation _lazyValue = s_unset; + internal LazyVariableInitializerOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BasePropertyInitializerOperation : BaseSymbolInitializerOperation, IPropertyInitializerOperation + { + internal BasePropertyInitializerOperation(ImmutableArray initializedProperties, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, OperationKind.PropertyInitializer, semanticModel, syntax, type, constantValue, isImplicit) + { + InitializedProperties = initializedProperties; + } + public ImmutableArray InitializedProperties { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitPropertyInitializer(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitPropertyInitializer(this, argument); + } + internal sealed partial class PropertyInitializerOperation : BasePropertyInitializerOperation, IPropertyInitializerOperation + { + internal PropertyInitializerOperation(ImmutableArray initializedProperties, ImmutableArray locals, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(initializedProperties, locals, semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + } + public override IOperation Value { get; } + } + internal abstract partial class LazyPropertyInitializerOperation : BasePropertyInitializerOperation, IPropertyInitializerOperation + { + private IOperation _lazyValue = s_unset; + internal LazyPropertyInitializerOperation(ImmutableArray initializedProperties, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(initializedProperties, locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseParameterInitializerOperation : BaseSymbolInitializerOperation, IParameterInitializerOperation + { + internal BaseParameterInitializerOperation(IParameterSymbol parameter, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, OperationKind.ParameterInitializer, semanticModel, syntax, type, constantValue, isImplicit) + { + Parameter = parameter; + } + public IParameterSymbol Parameter { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitParameterInitializer(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitParameterInitializer(this, argument); + } + internal sealed partial class ParameterInitializerOperation : BaseParameterInitializerOperation, IParameterInitializerOperation + { + internal ParameterInitializerOperation(IParameterSymbol parameter, ImmutableArray locals, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(parameter, locals, semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + } + public override IOperation Value { get; } + } + internal abstract partial class LazyParameterInitializerOperation : BaseParameterInitializerOperation, IParameterInitializerOperation + { + private IOperation _lazyValue = s_unset; + internal LazyParameterInitializerOperation(IParameterSymbol parameter, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(parameter, locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseArrayInitializerOperation : Operation, IArrayInitializerOperation + { + internal BaseArrayInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ArrayInitializer, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract ImmutableArray ElementValues { get; } + public override IEnumerable Children + { + get + { + foreach (var child in ElementValues) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitArrayInitializer(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitArrayInitializer(this, argument); + } + internal sealed partial class ArrayInitializerOperation : BaseArrayInitializerOperation, IArrayInitializerOperation + { + internal ArrayInitializerOperation(ImmutableArray elementValues, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + ElementValues = SetParentOperation(elementValues, this); + } + public override ImmutableArray ElementValues { get; } + } + internal abstract partial class LazyArrayInitializerOperation : BaseArrayInitializerOperation, IArrayInitializerOperation + { + private ImmutableArray _lazyElementValues; + internal LazyArrayInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateElementValues(); + public override ImmutableArray ElementValues + { + get + { + if (_lazyElementValues.IsDefault) + { + ImmutableArray elementValues = CreateElementValues(); + SetParentOperation(elementValues, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyElementValues, elementValues, default); + } + return _lazyElementValues; + } + } + } + internal abstract partial class BaseVariableDeclaratorOperation : Operation, IVariableDeclaratorOperation + { + internal BaseVariableDeclaratorOperation(ILocalSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.VariableDeclarator, semanticModel, syntax, type, constantValue, isImplicit) + { + Symbol = symbol; + } + public ILocalSymbol Symbol { get; } + public abstract IVariableInitializerOperation Initializer { get; } + public abstract ImmutableArray IgnoredArguments { get; } + public override IEnumerable Children + { + get + { + foreach (var child in IgnoredArguments) + { + if (child is object) yield return child; + } + if (Initializer is object) yield return Initializer; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitVariableDeclarator(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitVariableDeclarator(this, argument); + } + internal sealed partial class VariableDeclaratorOperation : BaseVariableDeclaratorOperation, IVariableDeclaratorOperation + { + internal VariableDeclaratorOperation(ILocalSymbol symbol, IVariableInitializerOperation initializer, ImmutableArray ignoredArguments, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(symbol, semanticModel, syntax, type, constantValue, isImplicit) + { + Initializer = SetParentOperation(initializer, this); + IgnoredArguments = SetParentOperation(ignoredArguments, this); + } + public override IVariableInitializerOperation Initializer { get; } + public override ImmutableArray IgnoredArguments { get; } + } + internal abstract partial class LazyVariableDeclaratorOperation : BaseVariableDeclaratorOperation, IVariableDeclaratorOperation + { + private IVariableInitializerOperation _lazyInitializer = s_unsetVariableInitializer; + private ImmutableArray _lazyIgnoredArguments; + internal LazyVariableDeclaratorOperation(ILocalSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(symbol, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IVariableInitializerOperation CreateInitializer(); + public override IVariableInitializerOperation Initializer + { + get + { + if (_lazyInitializer == s_unsetVariableInitializer) + { + IVariableInitializerOperation initializer = CreateInitializer(); + SetParentOperation(initializer, this); + Interlocked.CompareExchange(ref _lazyInitializer, initializer, s_unsetVariableInitializer); + } + return _lazyInitializer; + } + } + protected abstract ImmutableArray CreateIgnoredArguments(); + public override ImmutableArray IgnoredArguments + { + get + { + if (_lazyIgnoredArguments.IsDefault) + { + ImmutableArray ignoredArguments = CreateIgnoredArguments(); + SetParentOperation(ignoredArguments, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyIgnoredArguments, ignoredArguments, default); + } + return _lazyIgnoredArguments; + } + } + } + internal abstract partial class BaseVariableDeclarationOperation : Operation, IVariableDeclarationOperation + { + internal BaseVariableDeclarationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.VariableDeclaration, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract ImmutableArray Declarators { get; } + public abstract IVariableInitializerOperation Initializer { get; } + public abstract ImmutableArray IgnoredDimensions { get; } + public override IEnumerable Children + { + get + { + foreach (var child in IgnoredDimensions) + { + if (child is object) yield return child; + } + foreach (var child in Declarators) + { + if (child is object) yield return child; + } + if (Initializer is object) yield return Initializer; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitVariableDeclaration(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitVariableDeclaration(this, argument); + } + internal sealed partial class VariableDeclarationOperation : BaseVariableDeclarationOperation, IVariableDeclarationOperation + { + internal VariableDeclarationOperation(ImmutableArray declarators, IVariableInitializerOperation initializer, ImmutableArray ignoredDimensions, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Declarators = SetParentOperation(declarators, this); + Initializer = SetParentOperation(initializer, this); + IgnoredDimensions = SetParentOperation(ignoredDimensions, this); + } + public override ImmutableArray Declarators { get; } + public override IVariableInitializerOperation Initializer { get; } + public override ImmutableArray IgnoredDimensions { get; } + } + internal abstract partial class LazyVariableDeclarationOperation : BaseVariableDeclarationOperation, IVariableDeclarationOperation + { + private ImmutableArray _lazyDeclarators; + private IVariableInitializerOperation _lazyInitializer = s_unsetVariableInitializer; + private ImmutableArray _lazyIgnoredDimensions; + internal LazyVariableDeclarationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateDeclarators(); + public override ImmutableArray Declarators + { + get + { + if (_lazyDeclarators.IsDefault) + { + ImmutableArray declarators = CreateDeclarators(); + SetParentOperation(declarators, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDeclarators, declarators, default); + } + return _lazyDeclarators; + } + } + protected abstract IVariableInitializerOperation CreateInitializer(); + public override IVariableInitializerOperation Initializer + { + get + { + if (_lazyInitializer == s_unsetVariableInitializer) + { + IVariableInitializerOperation initializer = CreateInitializer(); + SetParentOperation(initializer, this); + Interlocked.CompareExchange(ref _lazyInitializer, initializer, s_unsetVariableInitializer); + } + return _lazyInitializer; + } + } + protected abstract ImmutableArray CreateIgnoredDimensions(); + public override ImmutableArray IgnoredDimensions + { + get + { + if (_lazyIgnoredDimensions.IsDefault) + { + ImmutableArray ignoredDimensions = CreateIgnoredDimensions(); + SetParentOperation(ignoredDimensions, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyIgnoredDimensions, ignoredDimensions, default); + } + return _lazyIgnoredDimensions; + } + } + } + internal abstract partial class BaseArgumentOperation : Operation, IArgumentOperation + { + internal BaseArgumentOperation(ArgumentKind argumentKind, IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Argument, semanticModel, syntax, type, constantValue, isImplicit) + { + ArgumentKind = argumentKind; + Parameter = parameter; + } + public ArgumentKind ArgumentKind { get; } + public IParameterSymbol Parameter { get; } + public abstract IOperation Value { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitArgument(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitArgument(this, argument); + } + internal sealed partial class ArgumentOperation : BaseArgumentOperation, IArgumentOperation + { + internal ArgumentOperation(ArgumentKind argumentKind, IParameterSymbol parameter, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(argumentKind, parameter, semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + } + public override IOperation Value { get; } + } + internal abstract partial class LazyArgumentOperation : BaseArgumentOperation, IArgumentOperation + { + private IOperation _lazyValue = s_unset; + internal LazyArgumentOperation(ArgumentKind argumentKind, IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(argumentKind, parameter, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseCatchClauseOperation : Operation, ICatchClauseOperation + { + internal BaseCatchClauseOperation(ITypeSymbol exceptionType, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.CatchClause, semanticModel, syntax, type, constantValue, isImplicit) + { + ExceptionType = exceptionType; + Locals = locals; + } + public abstract IOperation ExceptionDeclarationOrExpression { get; } + public ITypeSymbol ExceptionType { get; } + public ImmutableArray Locals { get; } + public abstract IOperation Filter { get; } + public abstract IBlockOperation Handler { get; } + public override IEnumerable Children + { + get + { + if (ExceptionDeclarationOrExpression is object) yield return ExceptionDeclarationOrExpression; + if (Filter is object) yield return Filter; + if (Handler is object) yield return Handler; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitCatchClause(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitCatchClause(this, argument); + } + internal sealed partial class CatchClauseOperation : BaseCatchClauseOperation, ICatchClauseOperation + { + internal CatchClauseOperation(IOperation exceptionDeclarationOrExpression, ITypeSymbol exceptionType, ImmutableArray locals, IOperation filter, IBlockOperation handler, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(exceptionType, locals, semanticModel, syntax, type, constantValue, isImplicit) + { + ExceptionDeclarationOrExpression = SetParentOperation(exceptionDeclarationOrExpression, this); + Filter = SetParentOperation(filter, this); + Handler = SetParentOperation(handler, this); + } + public override IOperation ExceptionDeclarationOrExpression { get; } + public override IOperation Filter { get; } + public override IBlockOperation Handler { get; } + } + internal abstract partial class LazyCatchClauseOperation : BaseCatchClauseOperation, ICatchClauseOperation + { + private IOperation _lazyExceptionDeclarationOrExpression = s_unset; + private IOperation _lazyFilter = s_unset; + private IBlockOperation _lazyHandler = s_unsetBlock; + internal LazyCatchClauseOperation(ITypeSymbol exceptionType, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(exceptionType, locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateExceptionDeclarationOrExpression(); + public override IOperation ExceptionDeclarationOrExpression + { + get + { + if (_lazyExceptionDeclarationOrExpression == s_unset) + { + IOperation exceptionDeclarationOrExpression = CreateExceptionDeclarationOrExpression(); + SetParentOperation(exceptionDeclarationOrExpression, this); + Interlocked.CompareExchange(ref _lazyExceptionDeclarationOrExpression, exceptionDeclarationOrExpression, s_unset); + } + return _lazyExceptionDeclarationOrExpression; + } + } + protected abstract IOperation CreateFilter(); + public override IOperation Filter + { + get + { + if (_lazyFilter == s_unset) + { + IOperation filter = CreateFilter(); + SetParentOperation(filter, this); + Interlocked.CompareExchange(ref _lazyFilter, filter, s_unset); + } + return _lazyFilter; + } + } + protected abstract IBlockOperation CreateHandler(); + public override IBlockOperation Handler + { + get + { + if (_lazyHandler == s_unsetBlock) + { + IBlockOperation handler = CreateHandler(); + SetParentOperation(handler, this); + Interlocked.CompareExchange(ref _lazyHandler, handler, s_unsetBlock); + } + return _lazyHandler; + } + } + } + internal abstract partial class BaseSwitchCaseOperation : Operation, ISwitchCaseOperation + { + internal BaseSwitchCaseOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.SwitchCase, semanticModel, syntax, type, constantValue, isImplicit) + { + Locals = locals; + } + public abstract ImmutableArray Clauses { get; } + public abstract ImmutableArray Body { get; } + public ImmutableArray Locals { get; } + public override IEnumerable Children + { + get + { + foreach (var child in Clauses) + { + if (child is object) yield return child; + } + foreach (var child in Body) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitSwitchCase(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitSwitchCase(this, argument); + } + internal sealed partial class SwitchCaseOperation : BaseSwitchCaseOperation, ISwitchCaseOperation + { + internal SwitchCaseOperation(ImmutableArray clauses, ImmutableArray body, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit) + { + Clauses = SetParentOperation(clauses, this); + Body = SetParentOperation(body, this); + } + public override ImmutableArray Clauses { get; } + public override ImmutableArray Body { get; } + } + internal abstract partial class LazySwitchCaseOperation : BaseSwitchCaseOperation, ISwitchCaseOperation + { + private ImmutableArray _lazyClauses; + private ImmutableArray _lazyBody; + internal LazySwitchCaseOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateClauses(); + public override ImmutableArray Clauses + { + get + { + if (_lazyClauses.IsDefault) + { + ImmutableArray clauses = CreateClauses(); + SetParentOperation(clauses, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyClauses, clauses, default); + } + return _lazyClauses; + } + } + protected abstract ImmutableArray CreateBody(); + public override ImmutableArray Body + { + get + { + if (_lazyBody.IsDefault) + { + ImmutableArray body = CreateBody(); + SetParentOperation(body, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyBody, body, default); + } + return _lazyBody; + } + } + } + internal abstract partial class BaseCaseClauseOperation : Operation, ICaseClauseOperation + { + protected BaseCaseClauseOperation(CaseKind caseKind, ILabelSymbol label, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) + { + CaseKind = caseKind; + Label = label; + } + public CaseKind CaseKind { get; } + public ILabelSymbol Label { get; } + } + internal sealed partial class DefaultCaseClauseOperation : BaseCaseClauseOperation, IDefaultCaseClauseOperation + { + internal DefaultCaseClauseOperation(CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(caseKind, label, OperationKind.CaseClause, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children => Array.Empty(); + public override void Accept(OperationVisitor visitor) => visitor.VisitDefaultCaseClause(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDefaultCaseClause(this, argument); + } + internal abstract partial class BaseRangeCaseClauseOperation : BaseCaseClauseOperation, IRangeCaseClauseOperation + { + internal BaseRangeCaseClauseOperation(CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(caseKind, label, OperationKind.CaseClause, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation MinimumValue { get; } + public abstract IOperation MaximumValue { get; } + public override IEnumerable Children + { + get + { + if (MinimumValue is object) yield return MinimumValue; + if (MaximumValue is object) yield return MaximumValue; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitRangeCaseClause(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitRangeCaseClause(this, argument); + } + internal sealed partial class RangeCaseClauseOperation : BaseRangeCaseClauseOperation, IRangeCaseClauseOperation + { + internal RangeCaseClauseOperation(IOperation minimumValue, IOperation maximumValue, CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(caseKind, label, semanticModel, syntax, type, constantValue, isImplicit) + { + MinimumValue = SetParentOperation(minimumValue, this); + MaximumValue = SetParentOperation(maximumValue, this); + } + public override IOperation MinimumValue { get; } + public override IOperation MaximumValue { get; } + } + internal abstract partial class LazyRangeCaseClauseOperation : BaseRangeCaseClauseOperation, IRangeCaseClauseOperation + { + private IOperation _lazyMinimumValue = s_unset; + private IOperation _lazyMaximumValue = s_unset; + internal LazyRangeCaseClauseOperation(CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(caseKind, label, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateMinimumValue(); + public override IOperation MinimumValue + { + get + { + if (_lazyMinimumValue == s_unset) + { + IOperation minimumValue = CreateMinimumValue(); + SetParentOperation(minimumValue, this); + Interlocked.CompareExchange(ref _lazyMinimumValue, minimumValue, s_unset); + } + return _lazyMinimumValue; + } + } + protected abstract IOperation CreateMaximumValue(); + public override IOperation MaximumValue + { + get + { + if (_lazyMaximumValue == s_unset) + { + IOperation maximumValue = CreateMaximumValue(); + SetParentOperation(maximumValue, this); + Interlocked.CompareExchange(ref _lazyMaximumValue, maximumValue, s_unset); + } + return _lazyMaximumValue; + } + } + } + internal abstract partial class BaseRelationalCaseClauseOperation : BaseCaseClauseOperation, IRelationalCaseClauseOperation + { + internal BaseRelationalCaseClauseOperation(BinaryOperatorKind relation, CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(caseKind, label, OperationKind.CaseClause, semanticModel, syntax, type, constantValue, isImplicit) + { + Relation = relation; + } + public abstract IOperation Value { get; } + public BinaryOperatorKind Relation { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitRelationalCaseClause(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitRelationalCaseClause(this, argument); + } + internal sealed partial class RelationalCaseClauseOperation : BaseRelationalCaseClauseOperation, IRelationalCaseClauseOperation + { + internal RelationalCaseClauseOperation(IOperation value, BinaryOperatorKind relation, CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(relation, caseKind, label, semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + } + public override IOperation Value { get; } + } + internal abstract partial class LazyRelationalCaseClauseOperation : BaseRelationalCaseClauseOperation, IRelationalCaseClauseOperation + { + private IOperation _lazyValue = s_unset; + internal LazyRelationalCaseClauseOperation(BinaryOperatorKind relation, CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(relation, caseKind, label, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseSingleValueCaseClauseOperation : BaseCaseClauseOperation, ISingleValueCaseClauseOperation + { + internal BaseSingleValueCaseClauseOperation(CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(caseKind, label, OperationKind.CaseClause, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Value { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitSingleValueCaseClause(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitSingleValueCaseClause(this, argument); + } + internal sealed partial class SingleValueCaseClauseOperation : BaseSingleValueCaseClauseOperation, ISingleValueCaseClauseOperation + { + internal SingleValueCaseClauseOperation(IOperation value, CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(caseKind, label, semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + } + public override IOperation Value { get; } + } + internal abstract partial class LazySingleValueCaseClauseOperation : BaseSingleValueCaseClauseOperation, ISingleValueCaseClauseOperation + { + private IOperation _lazyValue = s_unset; + internal LazySingleValueCaseClauseOperation(CaseKind caseKind, ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(caseKind, label, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseInterpolatedStringContentOperation : Operation, IInterpolatedStringContentOperation + { + protected BaseInterpolatedStringContentOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) { } + } + internal abstract partial class BaseInterpolatedStringTextOperation : BaseInterpolatedStringContentOperation, IInterpolatedStringTextOperation + { + internal BaseInterpolatedStringTextOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.InterpolatedStringText, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Text { get; } + public override IEnumerable Children + { + get + { + if (Text is object) yield return Text; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitInterpolatedStringText(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitInterpolatedStringText(this, argument); + } + internal sealed partial class InterpolatedStringTextOperation : BaseInterpolatedStringTextOperation, IInterpolatedStringTextOperation + { + internal InterpolatedStringTextOperation(IOperation text, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Text = SetParentOperation(text, this); + } + public override IOperation Text { get; } + } + internal abstract partial class LazyInterpolatedStringTextOperation : BaseInterpolatedStringTextOperation, IInterpolatedStringTextOperation + { + private IOperation _lazyText = s_unset; + internal LazyInterpolatedStringTextOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateText(); + public override IOperation Text + { + get + { + if (_lazyText == s_unset) + { + IOperation text = CreateText(); + SetParentOperation(text, this); + Interlocked.CompareExchange(ref _lazyText, text, s_unset); + } + return _lazyText; + } + } + } + internal abstract partial class BaseInterpolationOperation : BaseInterpolatedStringContentOperation, IInterpolationOperation + { + internal BaseInterpolationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Interpolation, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Expression { get; } + public abstract IOperation Alignment { get; } + public abstract IOperation FormatString { get; } + public override IEnumerable Children + { + get + { + if (Expression is object) yield return Expression; + if (Alignment is object) yield return Alignment; + if (FormatString is object) yield return FormatString; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitInterpolation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitInterpolation(this, argument); + } + internal sealed partial class InterpolationOperation : BaseInterpolationOperation, IInterpolationOperation + { + internal InterpolationOperation(IOperation expression, IOperation alignment, IOperation formatString, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Expression = SetParentOperation(expression, this); + Alignment = SetParentOperation(alignment, this); + FormatString = SetParentOperation(formatString, this); + } + public override IOperation Expression { get; } + public override IOperation Alignment { get; } + public override IOperation FormatString { get; } + } + internal abstract partial class LazyInterpolationOperation : BaseInterpolationOperation, IInterpolationOperation + { + private IOperation _lazyExpression = s_unset; + private IOperation _lazyAlignment = s_unset; + private IOperation _lazyFormatString = s_unset; + internal LazyInterpolationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateExpression(); + public override IOperation Expression + { + get + { + if (_lazyExpression == s_unset) + { + IOperation expression = CreateExpression(); + SetParentOperation(expression, this); + Interlocked.CompareExchange(ref _lazyExpression, expression, s_unset); + } + return _lazyExpression; + } + } + protected abstract IOperation CreateAlignment(); + public override IOperation Alignment + { + get + { + if (_lazyAlignment == s_unset) + { + IOperation alignment = CreateAlignment(); + SetParentOperation(alignment, this); + Interlocked.CompareExchange(ref _lazyAlignment, alignment, s_unset); + } + return _lazyAlignment; + } + } + protected abstract IOperation CreateFormatString(); + public override IOperation FormatString + { + get + { + if (_lazyFormatString == s_unset) + { + IOperation formatString = CreateFormatString(); + SetParentOperation(formatString, this); + Interlocked.CompareExchange(ref _lazyFormatString, formatString, s_unset); + } + return _lazyFormatString; + } + } + } + internal abstract partial class BasePatternOperation : Operation, IPatternOperation + { + protected BasePatternOperation(ITypeSymbol inputType, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) + { + InputType = inputType; + } + public ITypeSymbol InputType { get; } + } + internal abstract partial class BaseConstantPatternOperation : BasePatternOperation, IConstantPatternOperation + { + internal BaseConstantPatternOperation(ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(inputType, OperationKind.ConstantPattern, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Value { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitConstantPattern(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitConstantPattern(this, argument); + } + internal sealed partial class ConstantPatternOperation : BaseConstantPatternOperation, IConstantPatternOperation + { + internal ConstantPatternOperation(IOperation value, ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(inputType, semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + } + public override IOperation Value { get; } + } + internal abstract partial class LazyConstantPatternOperation : BaseConstantPatternOperation, IConstantPatternOperation + { + private IOperation _lazyValue = s_unset; + internal LazyConstantPatternOperation(ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(inputType, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal sealed partial class DeclarationPatternOperation : BasePatternOperation, IDeclarationPatternOperation + { + internal DeclarationPatternOperation(ITypeSymbol matchedType, bool matchesNull, ISymbol declaredSymbol, ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(inputType, OperationKind.DeclarationPattern, semanticModel, syntax, type, constantValue, isImplicit) + { + MatchedType = matchedType; + MatchesNull = matchesNull; + DeclaredSymbol = declaredSymbol; + } + public ITypeSymbol MatchedType { get; } + public bool MatchesNull { get; } + public ISymbol DeclaredSymbol { get; } public override IEnumerable Children => Array.Empty(); public override void Accept(OperationVisitor visitor) => visitor.VisitDeclarationPattern(this); public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDeclarationPattern(this, argument); } + internal abstract partial class BaseTupleBinaryOperation : Operation, ITupleBinaryOperation + { + internal BaseTupleBinaryOperation(BinaryOperatorKind operatorKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.TupleBinary, semanticModel, syntax, type, constantValue, isImplicit) + { + OperatorKind = operatorKind; + } + public BinaryOperatorKind OperatorKind { get; } + public abstract IOperation LeftOperand { get; } + public abstract IOperation RightOperand { get; } + public override IEnumerable Children + { + get + { + if (LeftOperand is object) yield return LeftOperand; + if (RightOperand is object) yield return RightOperand; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitTupleBinaryOperator(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitTupleBinaryOperator(this, argument); + } + internal sealed partial class TupleBinaryOperation : BaseTupleBinaryOperation, ITupleBinaryOperation + { + internal TupleBinaryOperation(BinaryOperatorKind operatorKind, IOperation leftOperand, IOperation rightOperand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(operatorKind, semanticModel, syntax, type, constantValue, isImplicit) + { + LeftOperand = SetParentOperation(leftOperand, this); + RightOperand = SetParentOperation(rightOperand, this); + } + public override IOperation LeftOperand { get; } + public override IOperation RightOperand { get; } + } + internal abstract partial class LazyTupleBinaryOperation : BaseTupleBinaryOperation, ITupleBinaryOperation + { + private IOperation _lazyLeftOperand = s_unset; + private IOperation _lazyRightOperand = s_unset; + internal LazyTupleBinaryOperation(BinaryOperatorKind operatorKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(operatorKind, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateLeftOperand(); + public override IOperation LeftOperand + { + get + { + if (_lazyLeftOperand == s_unset) + { + IOperation leftOperand = CreateLeftOperand(); + SetParentOperation(leftOperand, this); + Interlocked.CompareExchange(ref _lazyLeftOperand, leftOperand, s_unset); + } + return _lazyLeftOperand; + } + } + protected abstract IOperation CreateRightOperand(); + public override IOperation RightOperand + { + get + { + if (_lazyRightOperand == s_unset) + { + IOperation rightOperand = CreateRightOperand(); + SetParentOperation(rightOperand, this); + Interlocked.CompareExchange(ref _lazyRightOperand, rightOperand, s_unset); + } + return _lazyRightOperand; + } + } + } + internal abstract partial class BaseMethodBodyBaseOperation : Operation, IMethodBodyBaseOperation + { + protected BaseMethodBodyBaseOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(kind, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IBlockOperation BlockBody { get; } + public abstract IBlockOperation ExpressionBody { get; } + } + internal abstract partial class BaseMethodBodyOperation : BaseMethodBodyBaseOperation, IMethodBodyOperation + { + internal BaseMethodBodyOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.MethodBody, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children + { + get + { + if (BlockBody is object) yield return BlockBody; + if (ExpressionBody is object) yield return ExpressionBody; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitMethodBodyOperation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitMethodBodyOperation(this, argument); + } + internal sealed partial class MethodBodyOperation : BaseMethodBodyOperation, IMethodBodyOperation + { + internal MethodBodyOperation(IBlockOperation blockBody, IBlockOperation expressionBody, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + BlockBody = SetParentOperation(blockBody, this); + ExpressionBody = SetParentOperation(expressionBody, this); + } + public override IBlockOperation BlockBody { get; } + public override IBlockOperation ExpressionBody { get; } + } + internal abstract partial class LazyMethodBodyOperation : BaseMethodBodyOperation, IMethodBodyOperation + { + private IBlockOperation _lazyBlockBody = s_unsetBlock; + private IBlockOperation _lazyExpressionBody = s_unsetBlock; + internal LazyMethodBodyOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IBlockOperation CreateBlockBody(); + public override IBlockOperation BlockBody + { + get + { + if (_lazyBlockBody == s_unsetBlock) + { + IBlockOperation blockBody = CreateBlockBody(); + SetParentOperation(blockBody, this); + Interlocked.CompareExchange(ref _lazyBlockBody, blockBody, s_unsetBlock); + } + return _lazyBlockBody; + } + } + protected abstract IBlockOperation CreateExpressionBody(); + public override IBlockOperation ExpressionBody + { + get + { + if (_lazyExpressionBody == s_unsetBlock) + { + IBlockOperation expressionBody = CreateExpressionBody(); + SetParentOperation(expressionBody, this); + Interlocked.CompareExchange(ref _lazyExpressionBody, expressionBody, s_unsetBlock); + } + return _lazyExpressionBody; + } + } + } + internal abstract partial class BaseConstructorBodyOperation : BaseMethodBodyBaseOperation, IConstructorBodyOperation + { + internal BaseConstructorBodyOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ConstructorBody, semanticModel, syntax, type, constantValue, isImplicit) + { + Locals = locals; + } + public ImmutableArray Locals { get; } + public abstract IOperation Initializer { get; } + public override IEnumerable Children + { + get + { + if (Initializer is object) yield return Initializer; + if (BlockBody is object) yield return BlockBody; + if (ExpressionBody is object) yield return ExpressionBody; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitConstructorBodyOperation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitConstructorBodyOperation(this, argument); + } + internal sealed partial class ConstructorBodyOperation : BaseConstructorBodyOperation, IConstructorBodyOperation + { + internal ConstructorBodyOperation(ImmutableArray locals, IOperation initializer, IBlockOperation blockBody, IBlockOperation expressionBody, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit) + { + Initializer = SetParentOperation(initializer, this); + BlockBody = SetParentOperation(blockBody, this); + ExpressionBody = SetParentOperation(expressionBody, this); + } + public override IOperation Initializer { get; } + public override IBlockOperation BlockBody { get; } + public override IBlockOperation ExpressionBody { get; } + } + internal abstract partial class LazyConstructorBodyOperation : BaseConstructorBodyOperation, IConstructorBodyOperation + { + private IOperation _lazyInitializer = s_unset; + private IBlockOperation _lazyBlockBody = s_unsetBlock; + private IBlockOperation _lazyExpressionBody = s_unsetBlock; + internal LazyConstructorBodyOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateInitializer(); + public override IOperation Initializer + { + get + { + if (_lazyInitializer == s_unset) + { + IOperation initializer = CreateInitializer(); + SetParentOperation(initializer, this); + Interlocked.CompareExchange(ref _lazyInitializer, initializer, s_unset); + } + return _lazyInitializer; + } + } + protected abstract IBlockOperation CreateBlockBody(); + public override IBlockOperation BlockBody + { + get + { + if (_lazyBlockBody == s_unsetBlock) + { + IBlockOperation blockBody = CreateBlockBody(); + SetParentOperation(blockBody, this); + Interlocked.CompareExchange(ref _lazyBlockBody, blockBody, s_unsetBlock); + } + return _lazyBlockBody; + } + } + protected abstract IBlockOperation CreateExpressionBody(); + public override IBlockOperation ExpressionBody + { + get + { + if (_lazyExpressionBody == s_unsetBlock) + { + IBlockOperation expressionBody = CreateExpressionBody(); + SetParentOperation(expressionBody, this); + Interlocked.CompareExchange(ref _lazyExpressionBody, expressionBody, s_unsetBlock); + } + return _lazyExpressionBody; + } + } + } internal sealed partial class DiscardOperation : Operation, IDiscardOperation { internal DiscardOperation(IDiscardSymbol discardSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) @@ -2979,6 +7345,330 @@ internal StaticLocalInitializationSemaphoreOperation(ILocalSymbol local, Semanti public override void Accept(OperationVisitor visitor) => visitor.VisitStaticLocalInitializationSemaphore(this); public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitStaticLocalInitializationSemaphore(this, argument); } + internal abstract partial class BaseCoalesceAssignmentOperation : BaseAssignmentOperation, ICoalesceAssignmentOperation + { + internal BaseCoalesceAssignmentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.CoalesceAssignment, semanticModel, syntax, type, constantValue, isImplicit) { } + public override IEnumerable Children + { + get + { + if (Target is object) yield return Target; + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitCoalesceAssignment(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitCoalesceAssignment(this, argument); + } + internal sealed partial class CoalesceAssignmentOperation : BaseCoalesceAssignmentOperation, ICoalesceAssignmentOperation + { + internal CoalesceAssignmentOperation(IOperation target, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Target = SetParentOperation(target, this); + Value = SetParentOperation(value, this); + } + public override IOperation Target { get; } + public override IOperation Value { get; } + } + internal abstract partial class LazyCoalesceAssignmentOperation : BaseCoalesceAssignmentOperation, ICoalesceAssignmentOperation + { + private IOperation _lazyTarget = s_unset; + private IOperation _lazyValue = s_unset; + internal LazyCoalesceAssignmentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateTarget(); + public override IOperation Target + { + get + { + if (_lazyTarget == s_unset) + { + IOperation target = CreateTarget(); + SetParentOperation(target, this); + Interlocked.CompareExchange(ref _lazyTarget, target, s_unset); + } + return _lazyTarget; + } + } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BaseRangeOperation : Operation, IRangeOperation + { + internal BaseRangeOperation(bool isLifted, IMethodSymbol method, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.Range, semanticModel, syntax, type, constantValue, isImplicit) + { + IsLifted = isLifted; + Method = method; + } + public abstract IOperation LeftOperand { get; } + public abstract IOperation RightOperand { get; } + public bool IsLifted { get; } + public IMethodSymbol Method { get; } + public override IEnumerable Children + { + get + { + if (LeftOperand is object) yield return LeftOperand; + if (RightOperand is object) yield return RightOperand; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitRangeOperation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitRangeOperation(this, argument); + } + internal sealed partial class RangeOperation : BaseRangeOperation, IRangeOperation + { + internal RangeOperation(IOperation leftOperand, IOperation rightOperand, bool isLifted, IMethodSymbol method, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isLifted, method, semanticModel, syntax, type, constantValue, isImplicit) + { + LeftOperand = SetParentOperation(leftOperand, this); + RightOperand = SetParentOperation(rightOperand, this); + } + public override IOperation LeftOperand { get; } + public override IOperation RightOperand { get; } + } + internal abstract partial class LazyRangeOperation : BaseRangeOperation, IRangeOperation + { + private IOperation _lazyLeftOperand = s_unset; + private IOperation _lazyRightOperand = s_unset; + internal LazyRangeOperation(bool isLifted, IMethodSymbol method, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(isLifted, method, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateLeftOperand(); + public override IOperation LeftOperand + { + get + { + if (_lazyLeftOperand == s_unset) + { + IOperation leftOperand = CreateLeftOperand(); + SetParentOperation(leftOperand, this); + Interlocked.CompareExchange(ref _lazyLeftOperand, leftOperand, s_unset); + } + return _lazyLeftOperand; + } + } + protected abstract IOperation CreateRightOperand(); + public override IOperation RightOperand + { + get + { + if (_lazyRightOperand == s_unset) + { + IOperation rightOperand = CreateRightOperand(); + SetParentOperation(rightOperand, this); + Interlocked.CompareExchange(ref _lazyRightOperand, rightOperand, s_unset); + } + return _lazyRightOperand; + } + } + } + internal abstract partial class BaseReDimOperation : Operation, IReDimOperation + { + internal BaseReDimOperation(bool preserve, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ReDim, semanticModel, syntax, type, constantValue, isImplicit) + { + Preserve = preserve; + } + public abstract ImmutableArray Clauses { get; } + public bool Preserve { get; } + public override IEnumerable Children + { + get + { + foreach (var child in Clauses) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitReDim(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitReDim(this, argument); + } + internal sealed partial class ReDimOperation : BaseReDimOperation, IReDimOperation + { + internal ReDimOperation(ImmutableArray clauses, bool preserve, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(preserve, semanticModel, syntax, type, constantValue, isImplicit) + { + Clauses = SetParentOperation(clauses, this); + } + public override ImmutableArray Clauses { get; } + } + internal abstract partial class LazyReDimOperation : BaseReDimOperation, IReDimOperation + { + private ImmutableArray _lazyClauses; + internal LazyReDimOperation(bool preserve, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(preserve, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateClauses(); + public override ImmutableArray Clauses + { + get + { + if (_lazyClauses.IsDefault) + { + ImmutableArray clauses = CreateClauses(); + SetParentOperation(clauses, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyClauses, clauses, default); + } + return _lazyClauses; + } + } + } + internal abstract partial class BaseReDimClauseOperation : Operation, IReDimClauseOperation + { + internal BaseReDimClauseOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.ReDimClause, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Operand { get; } + public abstract ImmutableArray DimensionSizes { get; } + public override IEnumerable Children + { + get + { + if (Operand is object) yield return Operand; + foreach (var child in DimensionSizes) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitReDimClause(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitReDimClause(this, argument); + } + internal sealed partial class ReDimClauseOperation : BaseReDimClauseOperation, IReDimClauseOperation + { + internal ReDimClauseOperation(IOperation operand, ImmutableArray dimensionSizes, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Operand = SetParentOperation(operand, this); + DimensionSizes = SetParentOperation(dimensionSizes, this); + } + public override IOperation Operand { get; } + public override ImmutableArray DimensionSizes { get; } + } + internal abstract partial class LazyReDimClauseOperation : BaseReDimClauseOperation, IReDimClauseOperation + { + private IOperation _lazyOperand = s_unset; + private ImmutableArray _lazyDimensionSizes; + internal LazyReDimClauseOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateOperand(); + public override IOperation Operand + { + get + { + if (_lazyOperand == s_unset) + { + IOperation operand = CreateOperand(); + SetParentOperation(operand, this); + Interlocked.CompareExchange(ref _lazyOperand, operand, s_unset); + } + return _lazyOperand; + } + } + protected abstract ImmutableArray CreateDimensionSizes(); + public override ImmutableArray DimensionSizes + { + get + { + if (_lazyDimensionSizes.IsDefault) + { + ImmutableArray dimensionSizes = CreateDimensionSizes(); + SetParentOperation(dimensionSizes, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDimensionSizes, dimensionSizes, default); + } + return _lazyDimensionSizes; + } + } + } + internal abstract partial class BaseRecursivePatternOperation : BasePatternOperation, IRecursivePatternOperation + { + internal BaseRecursivePatternOperation(ITypeSymbol matchedType, ISymbol deconstructSymbol, ISymbol declaredSymbol, ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(inputType, OperationKind.RecursivePattern, semanticModel, syntax, type, constantValue, isImplicit) + { + MatchedType = matchedType; + DeconstructSymbol = deconstructSymbol; + DeclaredSymbol = declaredSymbol; + } + public ITypeSymbol MatchedType { get; } + public ISymbol DeconstructSymbol { get; } + public abstract ImmutableArray DeconstructionSubpatterns { get; } + public abstract ImmutableArray PropertySubpatterns { get; } + public ISymbol DeclaredSymbol { get; } + public override IEnumerable Children + { + get + { + foreach (var child in DeconstructionSubpatterns) + { + if (child is object) yield return child; + } + foreach (var child in PropertySubpatterns) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitRecursivePattern(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitRecursivePattern(this, argument); + } + internal sealed partial class RecursivePatternOperation : BaseRecursivePatternOperation, IRecursivePatternOperation + { + internal RecursivePatternOperation(ITypeSymbol matchedType, ISymbol deconstructSymbol, ImmutableArray deconstructionSubpatterns, ImmutableArray propertySubpatterns, ISymbol declaredSymbol, ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(matchedType, deconstructSymbol, declaredSymbol, inputType, semanticModel, syntax, type, constantValue, isImplicit) + { + DeconstructionSubpatterns = SetParentOperation(deconstructionSubpatterns, this); + PropertySubpatterns = SetParentOperation(propertySubpatterns, this); + } + public override ImmutableArray DeconstructionSubpatterns { get; } + public override ImmutableArray PropertySubpatterns { get; } + } + internal abstract partial class LazyRecursivePatternOperation : BaseRecursivePatternOperation, IRecursivePatternOperation + { + private ImmutableArray _lazyDeconstructionSubpatterns; + private ImmutableArray _lazyPropertySubpatterns; + internal LazyRecursivePatternOperation(ITypeSymbol matchedType, ISymbol deconstructSymbol, ISymbol declaredSymbol, ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(matchedType, deconstructSymbol, declaredSymbol, inputType, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract ImmutableArray CreateDeconstructionSubpatterns(); + public override ImmutableArray DeconstructionSubpatterns + { + get + { + if (_lazyDeconstructionSubpatterns.IsDefault) + { + ImmutableArray deconstructionSubpatterns = CreateDeconstructionSubpatterns(); + SetParentOperation(deconstructionSubpatterns, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDeconstructionSubpatterns, deconstructionSubpatterns, default); + } + return _lazyDeconstructionSubpatterns; + } + } + protected abstract ImmutableArray CreatePropertySubpatterns(); + public override ImmutableArray PropertySubpatterns + { + get + { + if (_lazyPropertySubpatterns.IsDefault) + { + ImmutableArray propertySubpatterns = CreatePropertySubpatterns(); + SetParentOperation(propertySubpatterns, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyPropertySubpatterns, propertySubpatterns, default); + } + return _lazyPropertySubpatterns; + } + } + } internal sealed partial class DiscardPatternOperation : BasePatternOperation, IDiscardPatternOperation { internal DiscardPatternOperation(ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) @@ -2987,6 +7677,395 @@ internal DiscardPatternOperation(ITypeSymbol inputType, SemanticModel semanticMo public override void Accept(OperationVisitor visitor) => visitor.VisitDiscardPattern(this); public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitDiscardPattern(this, argument); } + internal abstract partial class BaseSwitchExpressionOperation : Operation, ISwitchExpressionOperation + { + internal BaseSwitchExpressionOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.SwitchExpression, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Value { get; } + public abstract ImmutableArray Arms { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + foreach (var child in Arms) + { + if (child is object) yield return child; + } + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitSwitchExpression(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitSwitchExpression(this, argument); + } + internal sealed partial class SwitchExpressionOperation : BaseSwitchExpressionOperation, ISwitchExpressionOperation + { + internal SwitchExpressionOperation(IOperation value, ImmutableArray arms, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Value = SetParentOperation(value, this); + Arms = SetParentOperation(arms, this); + } + public override IOperation Value { get; } + public override ImmutableArray Arms { get; } + } + internal abstract partial class LazySwitchExpressionOperation : BaseSwitchExpressionOperation, ISwitchExpressionOperation + { + private IOperation _lazyValue = s_unset; + private ImmutableArray _lazyArms; + internal LazySwitchExpressionOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + protected abstract ImmutableArray CreateArms(); + public override ImmutableArray Arms + { + get + { + if (_lazyArms.IsDefault) + { + ImmutableArray arms = CreateArms(); + SetParentOperation(arms, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArms, arms, default); + } + return _lazyArms; + } + } + } + internal abstract partial class BaseSwitchExpressionArmOperation : Operation, ISwitchExpressionArmOperation + { + internal BaseSwitchExpressionArmOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.SwitchExpressionArm, semanticModel, syntax, type, constantValue, isImplicit) + { + Locals = locals; + } + public abstract IPatternOperation Pattern { get; } + public abstract IOperation Guard { get; } + public abstract IOperation Value { get; } + public ImmutableArray Locals { get; } + public override IEnumerable Children + { + get + { + if (Pattern is object) yield return Pattern; + if (Guard is object) yield return Guard; + if (Value is object) yield return Value; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitSwitchExpressionArm(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitSwitchExpressionArm(this, argument); + } + internal sealed partial class SwitchExpressionArmOperation : BaseSwitchExpressionArmOperation, ISwitchExpressionArmOperation + { + internal SwitchExpressionArmOperation(IPatternOperation pattern, IOperation guard, IOperation value, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit) + { + Pattern = SetParentOperation(pattern, this); + Guard = SetParentOperation(guard, this); + Value = SetParentOperation(value, this); + } + public override IPatternOperation Pattern { get; } + public override IOperation Guard { get; } + public override IOperation Value { get; } + } + internal abstract partial class LazySwitchExpressionArmOperation : BaseSwitchExpressionArmOperation, ISwitchExpressionArmOperation + { + private IPatternOperation _lazyPattern = s_unsetPattern; + private IOperation _lazyGuard = s_unset; + private IOperation _lazyValue = s_unset; + internal LazySwitchExpressionArmOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IPatternOperation CreatePattern(); + public override IPatternOperation Pattern + { + get + { + if (_lazyPattern == s_unsetPattern) + { + IPatternOperation pattern = CreatePattern(); + SetParentOperation(pattern, this); + Interlocked.CompareExchange(ref _lazyPattern, pattern, s_unsetPattern); + } + return _lazyPattern; + } + } + protected abstract IOperation CreateGuard(); + public override IOperation Guard + { + get + { + if (_lazyGuard == s_unset) + { + IOperation guard = CreateGuard(); + SetParentOperation(guard, this); + Interlocked.CompareExchange(ref _lazyGuard, guard, s_unset); + } + return _lazyGuard; + } + } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } + internal abstract partial class BasePropertySubpatternOperation : Operation, IPropertySubpatternOperation + { + internal BasePropertySubpatternOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.PropertySubpattern, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Member { get; } + public abstract IPatternOperation Pattern { get; } + public override IEnumerable Children + { + get + { + if (Member is object) yield return Member; + if (Pattern is object) yield return Pattern; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitPropertySubpattern(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitPropertySubpattern(this, argument); + } + internal sealed partial class PropertySubpatternOperation : BasePropertySubpatternOperation, IPropertySubpatternOperation + { + internal PropertySubpatternOperation(IOperation member, IPatternOperation pattern, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Member = SetParentOperation(member, this); + Pattern = SetParentOperation(pattern, this); + } + public override IOperation Member { get; } + public override IPatternOperation Pattern { get; } + } + internal abstract partial class LazyPropertySubpatternOperation : BasePropertySubpatternOperation, IPropertySubpatternOperation + { + private IOperation _lazyMember = s_unset; + private IPatternOperation _lazyPattern = s_unsetPattern; + internal LazyPropertySubpatternOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateMember(); + public override IOperation Member + { + get + { + if (_lazyMember == s_unset) + { + IOperation member = CreateMember(); + SetParentOperation(member, this); + Interlocked.CompareExchange(ref _lazyMember, member, s_unset); + } + return _lazyMember; + } + } + protected abstract IPatternOperation CreatePattern(); + public override IPatternOperation Pattern + { + get + { + if (_lazyPattern == s_unsetPattern) + { + IPatternOperation pattern = CreatePattern(); + SetParentOperation(pattern, this); + Interlocked.CompareExchange(ref _lazyPattern, pattern, s_unsetPattern); + } + return _lazyPattern; + } + } + } + internal abstract partial class BaseAggregateQueryOperation : Operation, IAggregateQueryOperation + { + internal BaseAggregateQueryOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.None, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Group { get; } + public abstract IOperation Aggregation { get; } + public override IEnumerable Children + { + get + { + if (Group is object) yield return Group; + if (Aggregation is object) yield return Aggregation; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitAggregateQuery(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitAggregateQuery(this, argument); + } + internal sealed partial class AggregateQueryOperation : BaseAggregateQueryOperation, IAggregateQueryOperation + { + internal AggregateQueryOperation(IOperation group, IOperation aggregation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Group = SetParentOperation(group, this); + Aggregation = SetParentOperation(aggregation, this); + } + public override IOperation Group { get; } + public override IOperation Aggregation { get; } + } + internal abstract partial class LazyAggregateQueryOperation : BaseAggregateQueryOperation, IAggregateQueryOperation + { + private IOperation _lazyGroup = s_unset; + private IOperation _lazyAggregation = s_unset; + internal LazyAggregateQueryOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateGroup(); + public override IOperation Group + { + get + { + if (_lazyGroup == s_unset) + { + IOperation group = CreateGroup(); + SetParentOperation(group, this); + Interlocked.CompareExchange(ref _lazyGroup, group, s_unset); + } + return _lazyGroup; + } + } + protected abstract IOperation CreateAggregation(); + public override IOperation Aggregation + { + get + { + if (_lazyAggregation == s_unset) + { + IOperation aggregation = CreateAggregation(); + SetParentOperation(aggregation, this); + Interlocked.CompareExchange(ref _lazyAggregation, aggregation, s_unset); + } + return _lazyAggregation; + } + } + } + internal abstract partial class BaseFixedOperation : Operation, IFixedOperation + { + internal BaseFixedOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.None, semanticModel, syntax, type, constantValue, isImplicit) + { + Locals = locals; + } + public ImmutableArray Locals { get; } + public abstract IVariableDeclarationGroupOperation Variables { get; } + public abstract IOperation Body { get; } + public override IEnumerable Children + { + get + { + if (Variables is object) yield return Variables; + if (Body is object) yield return Body; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitFixed(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitFixed(this, argument); + } + internal sealed partial class FixedOperation : BaseFixedOperation, IFixedOperation + { + internal FixedOperation(ImmutableArray locals, IVariableDeclarationGroupOperation variables, IOperation body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit) + { + Variables = SetParentOperation(variables, this); + Body = SetParentOperation(body, this); + } + public override IVariableDeclarationGroupOperation Variables { get; } + public override IOperation Body { get; } + } + internal abstract partial class LazyFixedOperation : BaseFixedOperation, IFixedOperation + { + private IVariableDeclarationGroupOperation _lazyVariables = s_unsetVariableDeclarationGroup; + private IOperation _lazyBody = s_unset; + internal LazyFixedOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(locals, semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IVariableDeclarationGroupOperation CreateVariables(); + public override IVariableDeclarationGroupOperation Variables + { + get + { + if (_lazyVariables == s_unsetVariableDeclarationGroup) + { + IVariableDeclarationGroupOperation variables = CreateVariables(); + SetParentOperation(variables, this); + Interlocked.CompareExchange(ref _lazyVariables, variables, s_unsetVariableDeclarationGroup); + } + return _lazyVariables; + } + } + protected abstract IOperation CreateBody(); + public override IOperation Body + { + get + { + if (_lazyBody == s_unset) + { + IOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unset); + } + return _lazyBody; + } + } + } + internal abstract partial class BaseNoPiaObjectCreationOperation : Operation, INoPiaObjectCreationOperation + { + internal BaseNoPiaObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.None, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IObjectOrCollectionInitializerOperation Initializer { get; } + public override IEnumerable Children + { + get + { + if (Initializer is object) yield return Initializer; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitNoPiaObjectCreation(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitNoPiaObjectCreation(this, argument); + } + internal sealed partial class NoPiaObjectCreationOperation : BaseNoPiaObjectCreationOperation, INoPiaObjectCreationOperation + { + internal NoPiaObjectCreationOperation(IObjectOrCollectionInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Initializer = SetParentOperation(initializer, this); + } + public override IObjectOrCollectionInitializerOperation Initializer { get; } + } + internal abstract partial class LazyNoPiaObjectCreationOperation : BaseNoPiaObjectCreationOperation, INoPiaObjectCreationOperation + { + private IObjectOrCollectionInitializerOperation _lazyInitializer = s_unsetObjectOrCollectionInitializer; + internal LazyNoPiaObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); + public override IObjectOrCollectionInitializerOperation Initializer + { + get + { + if (_lazyInitializer == s_unsetObjectOrCollectionInitializer) + { + IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); + SetParentOperation(initializer, this); + Interlocked.CompareExchange(ref _lazyInitializer, initializer, s_unsetObjectOrCollectionInitializer); + } + return _lazyInitializer; + } + } + } internal sealed partial class PlaceholderOperation : Operation, IPlaceholderOperation { internal PlaceholderOperation(PlaceholderKind placeholderKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) @@ -2999,6 +8078,113 @@ internal PlaceholderOperation(PlaceholderKind placeholderKind, SemanticModel sem public override void Accept(OperationVisitor visitor) => visitor.VisitPlaceholder(this); public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitPlaceholder(this, argument); } + internal abstract partial class BasePointerIndirectionReferenceOperation : Operation, IPointerIndirectionReferenceOperation + { + internal BasePointerIndirectionReferenceOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.None, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Pointer { get; } + public override IEnumerable Children + { + get + { + if (Pointer is object) yield return Pointer; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitPointerIndirectionReference(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitPointerIndirectionReference(this, argument); + } + internal sealed partial class PointerIndirectionReferenceOperation : BasePointerIndirectionReferenceOperation, IPointerIndirectionReferenceOperation + { + internal PointerIndirectionReferenceOperation(IOperation pointer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Pointer = SetParentOperation(pointer, this); + } + public override IOperation Pointer { get; } + } + internal abstract partial class LazyPointerIndirectionReferenceOperation : BasePointerIndirectionReferenceOperation, IPointerIndirectionReferenceOperation + { + private IOperation _lazyPointer = s_unset; + internal LazyPointerIndirectionReferenceOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreatePointer(); + public override IOperation Pointer + { + get + { + if (_lazyPointer == s_unset) + { + IOperation pointer = CreatePointer(); + SetParentOperation(pointer, this); + Interlocked.CompareExchange(ref _lazyPointer, pointer, s_unset); + } + return _lazyPointer; + } + } + } + internal abstract partial class BaseWithOperation : Operation, IWithOperation + { + internal BaseWithOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(OperationKind.None, semanticModel, syntax, type, constantValue, isImplicit) { } + public abstract IOperation Body { get; } + public abstract IOperation Value { get; } + public override IEnumerable Children + { + get + { + if (Value is object) yield return Value; + if (Body is object) yield return Body; + } + } + public override void Accept(OperationVisitor visitor) => visitor.VisitWith(this); + public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.VisitWith(this, argument); + } + internal sealed partial class WithOperation : BaseWithOperation, IWithOperation + { + internal WithOperation(IOperation body, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit) + { + Body = SetParentOperation(body, this); + Value = SetParentOperation(value, this); + } + public override IOperation Body { get; } + public override IOperation Value { get; } + } + internal abstract partial class LazyWithOperation : BaseWithOperation, IWithOperation + { + private IOperation _lazyBody = s_unset; + private IOperation _lazyValue = s_unset; + internal LazyWithOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) + : base(semanticModel, syntax, type, constantValue, isImplicit){ } + protected abstract IOperation CreateBody(); + public override IOperation Body + { + get + { + if (_lazyBody == s_unset) + { + IOperation body = CreateBody(); + SetParentOperation(body, this); + Interlocked.CompareExchange(ref _lazyBody, body, s_unset); + } + return _lazyBody; + } + } + protected abstract IOperation CreateValue(); + public override IOperation Value + { + get + { + if (_lazyValue == s_unset) + { + IOperation value = CreateValue(); + SetParentOperation(value, this); + Interlocked.CompareExchange(ref _lazyValue, value, s_unset); + } + return _lazyValue; + } + } + } #endregion #region Visitors public abstract partial class OperationVisitor diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs index 875b0c1090e5a..c6351ea2de8f3 100644 --- a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs @@ -1969,7 +1969,7 @@ public override IOperation VisitSimpleAssignment(ISimpleAssignmentOperation oper EvalStackFrame frame = PushStackFrame(); PushOperand(Visit(operation.Target)); IOperation value = Visit(operation.Value); - return PopStackFrame(frame, new SimpleAssignmentOperation(PopOperand(), operation.IsRef, value, null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation))); + return PopStackFrame(frame, new SimpleAssignmentOperation(operation.IsRef, PopOperand(), value, null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation))); } public override IOperation VisitCompoundAssignment(ICompoundAssignmentOperation operation, int? captureIdForResult) @@ -1979,9 +1979,9 @@ public override IOperation VisitCompoundAssignment(ICompoundAssignmentOperation PushOperand(Visit(compoundAssignment.Target)); IOperation value = Visit(compoundAssignment.Value); - return PopStackFrame(frame, new CompoundAssignmentOperation(PopOperand(), value, compoundAssignment.InConversionConvertible, compoundAssignment.OutConversionConvertible, - operation.OperatorKind, operation.IsLifted, operation.IsChecked, operation.OperatorMethod, semanticModel: null, - operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation))); + return PopStackFrame(frame, new CompoundAssignmentOperation(compoundAssignment.InConversionConvertible, compoundAssignment.OutConversionConvertible, operation.OperatorKind, operation.IsLifted, + operation.IsChecked, operation.OperatorMethod, PopOperand(), value, semanticModel: null, + syntax: operation.Syntax, type: operation.Type, constantValue: operation.ConstantValue, isImplicit: IsImplicit(operation))); } public override IOperation VisitArrayElementReference(IArrayElementReferenceOperation operation, int? captureIdForResult) @@ -2774,7 +2774,7 @@ private IOperation NullCheckAndConvertCoalesceValue(ICoalesceOperation operation } else { - convertedTestExpression = new ConversionOperation(possiblyUnwrappedValue, ((BaseCoalesceOperation)operation).ConvertibleValueConversion, + convertedTestExpression = new ConversionOperation(possiblyUnwrappedValue, ((BaseCoalesceOperation)operation).ValueConversionConvertible, isTryCast: false, isChecked: false, semanticModel: null, valueSyntax, operation.Type, constantValue: default, isImplicit: true); } @@ -2972,12 +2972,12 @@ void nullableValueTypeReturn() AddStatement( new SimpleAssignmentOperation( - OperationCloner.CloneOperation(locationCapture), isRef: false, - CreateConversion(whenNullValue, operation.Target.Type), + target: OperationCloner.CloneOperation(locationCapture), + value: CreateConversion(whenNullValue, operation.Target.Type), semanticModel: null, - operation.Syntax, - operation.Target.Type, + syntax: operation.Syntax, + type: operation.Target.Type, constantValue: operation.ConstantValue, isImplicit: true)); @@ -3009,8 +3009,8 @@ void standardReturn() EvalStackFrame whenNullFrame = PushStackFrame(); IOperation whenNullValue = Visit(operation.Value); - IOperation whenNullAssignment = new SimpleAssignmentOperation(OperationCloner.CloneOperation(locationCapture), isRef: false, whenNullValue, semanticModel: null, - operation.Syntax, operation.Type, constantValue: operation.ConstantValue, isImplicit: true); + IOperation whenNullAssignment = new SimpleAssignmentOperation(isRef: false, OperationCloner.CloneOperation(locationCapture), whenNullValue, semanticModel: null, + operation.Syntax, operation.Type, constantValue: operation.ConstantValue, isImplicit: true); if (isStatement) { @@ -3504,14 +3504,14 @@ private void AddExceptionStore(ITypeSymbol exceptionType, IOperation exceptionDe if (exceptionTarget != null) { AddStatement(new SimpleAssignmentOperation( - exceptionTarget, isRef: false, - new CaughtExceptionOperation(syntax, exceptionType), - semanticModel: null, - syntax, - type: null, - constantValue: default, - isImplicit: true)); + target: exceptionTarget, + value: new CaughtExceptionOperation(syntax, exceptionType), + semanticModel: null, + syntax: syntax, + type: null, + constantValue: default, + isImplicit: true)); } } } @@ -3529,7 +3529,7 @@ public override IOperation VisitReturn(IReturnOperation operation, int? captureI switch (operation.Kind) { case OperationKind.YieldReturn: - AddStatement(new ReturnOperation(OperationKind.YieldReturn, returnedValue, semanticModel: null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation))); + AddStatement(new ReturnOperation(returnedValue, OperationKind.YieldReturn, semanticModel: null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation))); break; case OperationKind.YieldBreak: @@ -4183,10 +4183,11 @@ IOperation getCurrent(IOperation enumeratorRef) if (info?.CurrentProperty != null) { return new PropertyReferenceOperation(info.CurrentProperty, - info.CurrentProperty.IsStatic ? null : enumeratorRef, - makeArguments(info.CurrentArguments), semanticModel: null, - operation.LoopControlVariable.Syntax, - info.CurrentProperty.Type, constantValue: default, isImplicit: true); + makeArguments(info.CurrentArguments), + info.CurrentProperty.IsStatic ? null : enumeratorRef, + semanticModel: null, + operation.LoopControlVariable.Syntax, + info.CurrentProperty.Type, constantValue: default, isImplicit: true); } else { @@ -4204,25 +4205,34 @@ IOperation getLoopControlVariableAssignment(IOperation current) ILocalSymbol local = declarator.Symbol; current = applyConversion(info?.ElementConversion, current, local.Type); - return new SimpleAssignmentOperation(new LocalReferenceOperation(local, isDeclaration: true, semanticModel: null, - declarator.Syntax, local.Type, constantValue: default, isImplicit: true), - isRef: local.RefKind != RefKind.None, current, semanticModel: null, declarator.Syntax, type: null, - constantValue: default, isImplicit: true); + return new SimpleAssignmentOperation(isRef: local.RefKind != RefKind.None, + new LocalReferenceOperation(local, + isDeclaration: true, + semanticModel: null, + declarator.Syntax, + local.Type, + constantValue: default, + isImplicit: true), + current, + semanticModel: null, + declarator.Syntax, + type: null, + constantValue: default, isImplicit: true); case OperationKind.Tuple: case OperationKind.DeclarationExpression: Debug.Assert(info?.ElementConversion?.ToCommonConversion().IsIdentity != false); return new DeconstructionAssignmentOperation(VisitPreservingTupleOperations(operation.LoopControlVariable), - current, semanticModel: null, - operation.LoopControlVariable.Syntax, operation.LoopControlVariable.Type, - constantValue: default, isImplicit: true); + current, semanticModel: null, + operation.LoopControlVariable.Syntax, operation.LoopControlVariable.Type, + constantValue: default, isImplicit: true); default: - return new SimpleAssignmentOperation(Visit(operation.LoopControlVariable), - isRef: false, // In C# this is an error case and VB doesn't support ref locals - current, semanticModel: null, operation.LoopControlVariable.Syntax, - operation.LoopControlVariable.Type, - constantValue: default, isImplicit: true); + return new SimpleAssignmentOperation(isRef: false, + Visit(operation.LoopControlVariable), // In C# this is an error case and VB doesn't support ref locals + current, semanticModel: null, operation.LoopControlVariable.Syntax, + operation.LoopControlVariable.Type, + constantValue: default, isImplicit: true); } } @@ -4503,11 +4513,11 @@ void initializeLoop() } IOperation initialValue = PopOperand(); - AddStatement(new SimpleAssignmentOperation(PopOperand(), // Loop control variable - isRef: false, - initialValue, - semanticModel: null, operation.InitialValue.Syntax, type: null, - constantValue: default, isImplicit: true)); + AddStatement(new SimpleAssignmentOperation(isRef: false, // Loop control variable + PopOperand(), + initialValue, + semanticModel: null, operation.InitialValue.Syntax, type: null, + constantValue: default, isImplicit: true)); } @@ -4821,14 +4831,14 @@ void incrementLoopControlVariable() _forToLoopBinaryOperatorRightOperand = null; controlVariableReferenceForAssignment = PopOperand(); - AddStatement(new SimpleAssignmentOperation(controlVariableReferenceForAssignment, - isRef: false, - increment, - semanticModel: null, - controlVariableReferenceForAssignment.Syntax, - type: null, - constantValue: default, - isImplicit: true)); + AddStatement(new SimpleAssignmentOperation(isRef: false, + controlVariableReferenceForAssignment, + increment, + semanticModel: null, + controlVariableReferenceForAssignment.Syntax, + type: null, + constantValue: default, + isImplicit: true)); PopStackFrameAndLeaveRegion(frame); } @@ -4872,18 +4882,18 @@ void incrementLoopControlVariable() controlVariableReferenceForAssignment = OperationCloner.CloneOperation(PeekOperand()); Debug.Assert(controlVariableReferenceForAssignment.Kind == OperationKind.FlowCaptureReference); - AddStatement(new SimpleAssignmentOperation(controlVariableReferenceForAssignment, - isRef: false, - new DefaultValueOperation(semanticModel: null, - controlVariableReferenceForAssignment.Syntax, - controlVariableReferenceForAssignment.Type, - constantValue: default, - isImplicit: true), - semanticModel: null, - controlVariableReferenceForAssignment.Syntax, - type: null, - constantValue: default, - isImplicit: true)); + AddStatement(new SimpleAssignmentOperation(isRef: false, + controlVariableReferenceForAssignment, + new DefaultValueOperation(semanticModel: null, + controlVariableReferenceForAssignment.Syntax, + controlVariableReferenceForAssignment.Type, + constantValue: default, + isImplicit: true), + semanticModel: null, + controlVariableReferenceForAssignment.Syntax, + type: null, + constantValue: default, + isImplicit: true)); UnconditionalBranch(afterIncrement); @@ -4921,14 +4931,14 @@ void incrementLoopControlVariable() increment = MakeNullable(increment, controlVariableReferenceForAssignment.Type); } - AddStatement(new SimpleAssignmentOperation(controlVariableReferenceForAssignment, - isRef: false, - increment, - semanticModel: null, - controlVariableReferenceForAssignment.Syntax, - type: null, - constantValue: default, - isImplicit: true)); + AddStatement(new SimpleAssignmentOperation(isRef: false, + controlVariableReferenceForAssignment, + increment, + semanticModel: null, + controlVariableReferenceForAssignment.Syntax, + type: null, + constantValue: default, + isImplicit: true)); PopStackFrame(frame, mergeNestedRegions: !isNullable); // We have a branch out in between when nullable is involved LeaveRegionIfAny(frame); @@ -5387,7 +5397,7 @@ private void HandleVariableDeclarator(IVariableDeclarationOperation declaration, // We can't use the IdentifierToken as the syntax for the local reference, so we use the // entire declarator as the node var localRef = new LocalReferenceOperation(localSymbol, isDeclaration: true, semanticModel: null, declarator.Syntax, localSymbol.Type, constantValue: default, isImplicit: true); - var assignment = new SimpleAssignmentOperation(localRef, isRef: localSymbol.IsRef, initializer, semanticModel: null, assignmentSyntax, localRef.Type, constantValue: default, isImplicit: true); + var assignment = new SimpleAssignmentOperation(isRef: localSymbol.IsRef, localRef, initializer, semanticModel: null, assignmentSyntax, localRef.Type, constantValue: default, isImplicit: true); AddStatement(assignment); PopStackFrameAndLeaveRegion(frame); @@ -5584,8 +5594,8 @@ void handleSimpleAssignment(ISimpleAssignmentOperation assignmentOperation) IOperation right = Visit(assignmentOperation.Value); IOperation left = popTarget(assignmentOperation.Target); - result = new SimpleAssignmentOperation(left, assignmentOperation.IsRef, right, semanticModel: null, assignmentOperation.Syntax, - assignmentOperation.Type, assignmentOperation.ConstantValue, IsImplicit(assignmentOperation)); + result = new SimpleAssignmentOperation(assignmentOperation.IsRef, left, right, semanticModel: null, assignmentOperation.Syntax, + assignmentOperation.Type, assignmentOperation.ConstantValue, IsImplicit(assignmentOperation)); } AddStatement(result); @@ -5717,7 +5727,7 @@ IOperation popTarget(IOperation originalTarget) var propertyReference = (IPropertyReferenceOperation)originalTarget; instance = (!propertyReference.Member.IsStatic && propertyReference.Instance != null) ? PopOperand() : null; ImmutableArray propertyArguments = PopArray(propertyReference.Arguments, RewriteArgumentFromArray); - return new PropertyReferenceOperation(propertyReference.Property, instance, propertyArguments, semanticModel: null, propertyReference.Syntax, + return new PropertyReferenceOperation(propertyReference.Property, propertyArguments, instance, semanticModel: null, propertyReference.Syntax, propertyReference.Type, propertyReference.ConstantValue, IsImplicit(propertyReference)); case OperationKind.ArrayElementReference: var arrayElementReference = (IArrayElementReferenceOperation)originalTarget; @@ -5786,10 +5796,10 @@ public override IOperation VisitAnonymousObjectCreation(IAnonymousObjectCreation var visitedPropertyInstance = new InstanceReferenceOperation(InstanceReferenceKind.ImplicitReceiver, semanticModel: null, propertyReference.Instance.Syntax, propertyReference.Instance.Type, propertyReference.Instance.ConstantValue, IsImplicit(propertyReference.Instance)); - IOperation visitedTarget = new PropertyReferenceOperation(propertyReference.Property, visitedPropertyInstance, ImmutableArray.Empty, + IOperation visitedTarget = new PropertyReferenceOperation(propertyReference.Property, ImmutableArray.Empty, visitedPropertyInstance, semanticModel: null, propertyReference.Syntax, propertyReference.Type, propertyReference.ConstantValue, IsImplicit(propertyReference)); IOperation visitedValue = visitAndCaptureInitializer(propertyReference.Property, simpleAssignment.Value); - var visitedAssignment = new SimpleAssignmentOperation(visitedTarget, isRef: simpleAssignment.IsRef, visitedValue, + var visitedAssignment = new SimpleAssignmentOperation(isRef: simpleAssignment.IsRef, visitedTarget, visitedValue, semanticModel: null, simpleAssignment.Syntax, simpleAssignment.Type, simpleAssignment.ConstantValue, IsImplicit(simpleAssignment)); initializerBuilder.Add(visitedAssignment); } @@ -6056,7 +6066,7 @@ private IOperation PopTargetAndWrapTupleIfNecessary(IOperation value) elementBuilder.Add(PopTargetAndWrapTupleIfNecessary(tuple.Elements[i])); } elementBuilder.ReverseContents(); - return new TupleOperation(elementBuilder.ToImmutableAndFree(), semanticModel: null, tuple.Syntax, tuple.Type, tuple.NaturalType, tuple.ConstantValue, IsImplicit(tuple)); + return new TupleOperation(elementBuilder.ToImmutableAndFree(), tuple.NaturalType, semanticModel: null, tuple.Syntax, tuple.Type, tuple.ConstantValue, IsImplicit(tuple)); } else { @@ -6255,7 +6265,7 @@ public override IOperation VisitPropertyReference(IPropertyReferenceOperation op IOperation instance = operation.Property.IsStatic ? null : operation.Instance; (IOperation visitedInstance, ImmutableArray visitedArguments) = VisitInstanceWithArguments(instance, operation.Arguments); PopStackFrame(frame); - return new PropertyReferenceOperation(operation.Property, visitedInstance, visitedArguments, semanticModel: null, + return new PropertyReferenceOperation(operation.Property, visitedArguments, visitedInstance, semanticModel: null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation)); } @@ -6356,7 +6366,7 @@ public override IOperation VisitPropertyInitializer(IPropertyInitializerOperatio arguments = ImmutableArray.Empty; } - IOperation propertyRef = new PropertyReferenceOperation(propertySymbol, instance, arguments, + IOperation propertyRef = new PropertyReferenceOperation(propertySymbol, arguments, instance, semanticModel: null, operation.Syntax, propertySymbol.Type, constantValue: default, isImplicit: true); VisitInitializer(rewrittenTarget: propertyRef, initializer: operation); } @@ -6369,8 +6379,8 @@ private void VisitInitializer(IOperation rewrittenTarget, ISymbolInitializerOper EnterRegion(new RegionBuilder(ControlFlowRegionKind.LocalLifetime, locals: initializer.Locals)); EvalStackFrame frame = PushStackFrame(); - var assignment = new SimpleAssignmentOperation(rewrittenTarget, isRef: false, Visit(initializer.Value), semanticModel: null, - initializer.Syntax, rewrittenTarget.Type, constantValue: default, isImplicit: true); + var assignment = new SimpleAssignmentOperation(isRef: false, rewrittenTarget, Visit(initializer.Value), semanticModel: null, + initializer.Syntax, rewrittenTarget.Type, constantValue: default, isImplicit: true); AddStatement(assignment); PopStackFrameAndLeaveRegion(frame); @@ -6463,9 +6473,8 @@ public override IOperation VisitAddressOf(IAddressOfOperation operation, int? ca public override IOperation VisitIncrementOrDecrement(IIncrementOrDecrementOperation operation, int? captureIdForResult) { - bool isDecrement = operation.Kind == OperationKind.Decrement; - return new IncrementOrDecrementOperation(isDecrement, operation.IsPostfix, operation.IsLifted, operation.IsChecked, Visit(operation.Target), operation.OperatorMethod, - semanticModel: null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation)); + return new IncrementOrDecrementOperation(operation.IsPostfix, operation.IsLifted, operation.IsChecked, Visit(operation.Target), operation.OperatorMethod, + operation.Kind, semanticModel: null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation)); } public override IOperation VisitDiscardOperation(IDiscardOperation operation, int? captureIdForResult) @@ -6519,7 +6528,7 @@ internal override IOperation VisitPlaceholder(IPlaceholderOperation operation, i public override IOperation VisitConversion(IConversionOperation operation, int? captureIdForResult) { - return new ConversionOperation(Visit(operation.Operand), ((BaseConversionOperation)operation).ConvertibleConversion, operation.IsTryCast, operation.IsChecked, semanticModel: null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation)); + return new ConversionOperation(Visit(operation.Operand), ((BaseConversionOperation)operation).ConversionConvertible, operation.IsTryCast, operation.IsChecked, semanticModel: null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation)); } public override IOperation VisitDefaultValue(IDefaultValueOperation operation, int? captureIdForResult) diff --git a/src/Compilers/Core/Portable/Operations/Operation.cs b/src/Compilers/Core/Portable/Operations/Operation.cs index 3ad72d146e8f4..6c91ae9d9a8f6 100644 --- a/src/Compilers/Core/Portable/Operations/Operation.cs +++ b/src/Compilers/Core/Portable/Operations/Operation.cs @@ -16,14 +16,22 @@ namespace Microsoft.CodeAnalysis /// internal abstract class Operation : IOperation { - protected static readonly IOperation s_unset = new EmptyOperation(null, null, null, default, isImplicit: true); - protected static readonly IBlockOperation s_unsetBlock = new BlockOperation(ImmutableArray.Empty, default, null, null, null, default, isImplicit: true); - protected static readonly IArrayInitializerOperation s_unsetArrayInitializer = new ArrayInitializerOperation(ImmutableArray.Empty, null, null, default, isImplicit: true); - protected static readonly IEventReferenceOperation s_unsetEventReference = new EventReferenceOperation(null, null, null, null, null, default, isImplicit: true); - protected static readonly IObjectOrCollectionInitializerOperation s_unsetObjectOrCollectionInitializer = new ObjectOrCollectionInitializerOperation(ImmutableArray.Empty, null, null, null, default, isImplicit: true); - protected static readonly IPatternOperation s_unsetPattern = new ConstantPatternOperation(null, null, null, null, isImplicit: true); - protected static readonly IVariableDeclarationGroupOperation s_unsetVariableDeclarationGroup = new VariableDeclarationGroupOperation(ImmutableArray.Empty, null, null, null, default, isImplicit: true); - protected static readonly IVariableInitializerOperation s_unsetVariableInitializer = new VariableInitializerOperation(null, null, null, null, default, isImplicit: true); + protected static readonly IOperation s_unset = new EmptyOperation( + semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true); + protected static readonly IBlockOperation s_unsetBlock = new BlockOperation( + operations: ImmutableArray.Empty, locals: default, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true); + protected static readonly IArrayInitializerOperation s_unsetArrayInitializer = new ArrayInitializerOperation( + elementValues: ImmutableArray.Empty, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true); + protected static readonly IEventReferenceOperation s_unsetEventReference = new EventReferenceOperation( + @event: null, instance: null, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true); + protected static readonly IObjectOrCollectionInitializerOperation s_unsetObjectOrCollectionInitializer = new ObjectOrCollectionInitializerOperation( + initializers: ImmutableArray.Empty, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true); + protected static readonly IPatternOperation s_unsetPattern = new ConstantPatternOperation( + value: null, inputType: null, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true); + protected static readonly IVariableDeclarationGroupOperation s_unsetVariableDeclarationGroup = new VariableDeclarationGroupOperation( + declarations: ImmutableArray.Empty, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true); + protected static readonly IVariableInitializerOperation s_unsetVariableInitializer = new VariableInitializerOperation( + locals: ImmutableArray.Empty, value: null, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: false); private readonly SemanticModel _owningSemanticModelOpt; // this will be lazily initialized. this will be initialized only once diff --git a/src/Compilers/Core/Portable/Operations/OperationCloner.cs b/src/Compilers/Core/Portable/Operations/OperationCloner.cs index 9b988a04775c3..cd079825564f7 100644 --- a/src/Compilers/Core/Portable/Operations/OperationCloner.cs +++ b/src/Compilers/Core/Portable/Operations/OperationCloner.cs @@ -78,7 +78,7 @@ public override IOperation VisitVariableDeclaration(IVariableDeclarationOperatio public override IOperation VisitConversion(IConversionOperation operation, object argument) { - return new ConversionOperation(Visit(operation.Operand), ((BaseConversionOperation)operation).ConvertibleConversion, operation.IsTryCast, operation.IsChecked, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new ConversionOperation(Visit(operation.Operand), ((BaseConversionOperation)operation).ConversionConvertible, operation.IsTryCast, operation.IsChecked, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitSwitch(ISwitchOperation operation, object argument) @@ -154,7 +154,7 @@ public override IOperation VisitEmpty(IEmptyOperation operation, object argument public override IOperation VisitReturn(IReturnOperation operation, object argument) { - return new ReturnOperation(operation.Kind, Visit(operation.ReturnedValue), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new ReturnOperation(Visit(operation.ReturnedValue), operation.Kind, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitLock(ILockOperation operation, object argument) @@ -257,7 +257,7 @@ public override IOperation VisitMethodReference(IMethodReferenceOperation operat public override IOperation VisitPropertyReference(IPropertyReferenceOperation operation, object argument) { - return new PropertyReferenceOperation(operation.Property, Visit(operation.Instance), VisitArray(operation.Arguments), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new PropertyReferenceOperation(operation.Property, VisitArray(operation.Arguments), Visit(operation.Instance), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitEventReference(IEventReferenceOperation operation, object argument) @@ -292,8 +292,8 @@ public override IOperation VisitUnaryOperator(IUnaryOperation operation, object public override IOperation VisitBinaryOperator(IBinaryOperation operation, object argument) { - return new BinaryOperation(operation.OperatorKind, Visit(operation.LeftOperand), Visit(operation.RightOperand), operation.IsLifted, - operation.IsChecked, operation.IsCompareText, operation.OperatorMethod, + return new BinaryOperation(operation.OperatorKind, Visit(operation.LeftOperand), Visit(operation.RightOperand), + operation.IsLifted, operation.IsChecked, operation.IsCompareText, operation.OperatorMethod, ((BaseBinaryOperation)operation).UnaryOperatorMethod, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } @@ -306,7 +306,7 @@ public override IOperation VisitTupleBinaryOperator(ITupleBinaryOperation operat public override IOperation VisitCompoundAssignment(ICompoundAssignmentOperation operation, object argument) { var compoundAssignment = (BaseCompoundAssignmentOperation)operation; - return new CompoundAssignmentOperation(Visit(operation.Target), Visit(operation.Value), compoundAssignment.InConversionConvertible, compoundAssignment.OutConversionConvertible, operation.OperatorKind, operation.IsLifted, operation.IsChecked, operation.OperatorMethod, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new CompoundAssignmentOperation(compoundAssignment.InConversionConvertible, compoundAssignment.OutConversionConvertible, operation.OperatorKind, operation.IsLifted, operation.IsChecked, operation.OperatorMethod, Visit(operation.Target), Visit(operation.Value), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitConditional(IConditionalOperation operation, object argument) @@ -317,7 +317,7 @@ public override IOperation VisitConditional(IConditionalOperation operation, obj public override IOperation VisitCoalesce(ICoalesceOperation operation, object argument) { var coalesceOperation = (BaseCoalesceOperation)operation; - return new CoalesceOperation(Visit(operation.Value), Visit(operation.WhenNull), coalesceOperation.ConvertibleValueConversion, coalesceOperation.OwningSemanticModel, + return new CoalesceOperation(Visit(operation.Value), Visit(operation.WhenNull), coalesceOperation.ValueConversionConvertible, coalesceOperation.OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } @@ -404,7 +404,7 @@ public override IOperation VisitMemberInitializer(IMemberInitializerOperation op public override IOperation VisitFieldInitializer(IFieldInitializerOperation operation, object argument) { - return new FieldInitializerOperation(operation.Locals, operation.InitializedFields, Visit(operation.Value), operation.Kind, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new FieldInitializerOperation(operation.InitializedFields, operation.Locals, Visit(operation.Value), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitVariableInitializer(IVariableInitializerOperation operation, object argument) @@ -414,12 +414,12 @@ public override IOperation VisitVariableInitializer(IVariableInitializerOperatio public override IOperation VisitPropertyInitializer(IPropertyInitializerOperation operation, object argument) { - return new PropertyInitializerOperation(operation.Locals, operation.InitializedProperties, Visit(operation.Value), operation.Kind, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new PropertyInitializerOperation(operation.InitializedProperties, operation.Locals, Visit(operation.Value), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitParameterInitializer(IParameterInitializerOperation operation, object argument) { - return new ParameterInitializerOperation(operation.Locals, operation.Parameter, Visit(operation.Value), operation.Kind, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new ParameterInitializerOperation(operation.Parameter, operation.Locals, Visit(operation.Value), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitArrayCreation(IArrayCreationOperation operation, object argument) @@ -434,7 +434,7 @@ public override IOperation VisitArrayInitializer(IArrayInitializerOperation oper public override IOperation VisitSimpleAssignment(ISimpleAssignmentOperation operation, object argument) { - return new SimpleAssignmentOperation(Visit(operation.Target), operation.IsRef, Visit(operation.Value), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new SimpleAssignmentOperation(operation.IsRef, Visit(operation.Target), Visit(operation.Value), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitDeconstructionAssignment(IDeconstructionAssignmentOperation operation, object argument) @@ -449,8 +449,7 @@ public override IOperation VisitDeclarationExpression(IDeclarationExpressionOper public override IOperation VisitIncrementOrDecrement(IIncrementOrDecrementOperation operation, object argument) { - bool isDecrement = operation.Kind == OperationKind.Decrement; - return new IncrementOrDecrementOperation(isDecrement, operation.IsPostfix, operation.IsLifted, operation.IsChecked, Visit(operation.Target), operation.OperatorMethod, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new IncrementOrDecrementOperation(operation.IsPostfix, operation.IsLifted, operation.IsChecked, Visit(operation.Target), operation.OperatorMethod, operation.Kind, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitParenthesized(IParenthesizedOperation operation, object argument) @@ -573,7 +572,7 @@ public override IOperation VisitPatternCaseClause(IPatternCaseClauseOperation op public override IOperation VisitTuple(ITupleOperation operation, object argument) { - return new TupleOperation(VisitArray(operation.Elements), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.NaturalType, operation.ConstantValue, operation.IsImplicit); + return new TupleOperation(VisitArray(operation.Elements), operation.NaturalType, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitTranslatedQuery(ITranslatedQueryOperation operation, object argument) diff --git a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml index 07b6ae4d96293..75f4e8f813455 100644 --- a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml +++ b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml @@ -77,7 +77,7 @@ - + Represents a switch operation with a value to be switched upon and switch cases. @@ -88,6 +88,13 @@ + + + + Locals declared within the switch operation with scope spanning across all . + + + Value to be switched upon. @@ -103,16 +110,9 @@ Exit label for the switch statement. - - - - Locals declared within the switch operation with scope spanning across all . - - - - + Represents a loop operation. @@ -149,7 +149,7 @@ - + @@ -179,8 +179,9 @@ + - + @@ -216,7 +217,7 @@ - + @@ -261,8 +262,9 @@ Optional list of comma separated next variables at loop bottom. + - + @@ -380,7 +382,7 @@ - + Represents a of operations that are executed while holding a lock onto the . @@ -401,8 +403,9 @@ Body of the lock, to be executed while holding the lock. + - + Represents a try operation for exception handling code with a body, catch clauses and a finally handler. @@ -434,7 +437,7 @@ - + Represents a of operations that are executed while using disposable . @@ -445,14 +448,14 @@ - + - Body of the using, over which the resources of the using are maintained. + Declaration introduced or resource held by the using. - + - Declaration introduced or resource held by the using. + Body of the using, over which the resources of the using are maintained. @@ -480,7 +483,7 @@ - + Represents a local function defined within a method. @@ -529,7 +532,7 @@ - + Represents an operation for raising an event. @@ -582,7 +585,7 @@ Value to be converted. - + Operator method used by the operation, null if the operation does not use an operator method. @@ -611,7 +614,7 @@ - + Represents an invocation of a method. @@ -654,7 +657,7 @@ - + Represents a reference to an array element. @@ -734,7 +737,7 @@ Instance of the type. Null if the reference is to a static/shared member. - + Referenced member. @@ -788,7 +791,7 @@ - + Represents a reference to a property. @@ -856,11 +859,6 @@ Operand. - - - Operator method used by the operation, null if the operation does not use an operator method. - - @@ -878,8 +876,13 @@ + + + Operator method used by the operation, null if the operation does not use an operator method. + + - + @@ -909,11 +912,6 @@ Right operand. - - - Operator method used by the operation, null if the operation does not use an operator method. - - @@ -938,8 +936,21 @@ + + + Operator method used by the operation, null if the operation does not use an operator method. + + + + + + True/False operator method used for short circuiting. + https://github.com/dotnet/roslyn/issues/27598 tracks exposing this information through public API + + + - + Represents a conditional operation with: @@ -978,7 +989,7 @@ - + Represents a coalesce operation with two operands: @@ -1037,7 +1048,7 @@ - + Represents creation of an object instance. @@ -1053,15 +1064,6 @@ Constructor to be invoked on the created instance. - - - Arguments of the object creation, excluding the instance argument. Arguments are in evaluation order. - - If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays. - Default values are supplied for optional arguments missing in source. - - - Object or collection initializer, if any. @@ -1085,7 +1087,7 @@ - + Represents the creation of an array instance. @@ -1196,7 +1198,7 @@ - + Represents a simple assignment operation. @@ -1213,7 +1215,7 @@ - + Represents a compound assignment that mutates the target with the result of a binary operation. @@ -1224,14 +1226,24 @@ - + - Kind of binary operation. + + Conversion applied to before the operation occurs. + - + - Operator method used by the operation, null if the operation does not use an operator method. + + Conversion applied to the result of the binary operation, before it is assigned back to + . + + + + + + Kind of binary operation. @@ -1248,19 +1260,9 @@ - - - - Conversion applied to before the operation occurs. - - - - + - - Conversion applied to the result of the binary operation, before it is assigned back to - . - + Operator method used by the operation, null if the operation does not use an operator method. @@ -1280,7 +1282,7 @@ - + Represents a binding of an event. @@ -1307,7 +1309,7 @@ - + Represents a conditionally accessed operation. Note that is used to refer to the value @@ -1405,7 +1407,7 @@ - + Represents an initialization of member within an object initializer with a nested object or collection initializer. @@ -1430,7 +1432,7 @@ - + "ICollectionElementInitializerOperation has been replaced with " + nameof(IInvocationOperation) + " and " + nameof(IDynamicInvocationOperation) @@ -1489,7 +1491,7 @@ - + Represents an object creation with a dynamically bound constructor. @@ -1545,7 +1547,7 @@ - + Represents a invocation that is dynamically bound. @@ -1574,7 +1576,7 @@ - + Represents an indexer access that is dynamically bound. @@ -1694,7 +1696,7 @@ - + Represents an operation that tests if a value matches a specific pattern. @@ -1731,16 +1733,6 @@ - - - Target of the assignment. - - - - - Operator method used by the operation, null if the operation does not use an operator method. - - @@ -1765,6 +1757,16 @@ + + + Target of the assignment. + + + + + Operator method used by the operation, null if the operation does not use an operator method. + + @@ -1784,7 +1786,7 @@ - + Represents a assignment with a deconstruction. @@ -1929,7 +1931,7 @@ - + Represents a single variable declarator and initializer. @@ -1968,7 +1970,7 @@ - + Represents a declarator that declares multiple individual variables. @@ -2010,7 +2012,7 @@ - + Represents an argument to a method invocation. @@ -2036,18 +2038,18 @@ Value supplied for the argument. - + Information of the conversion applied to the argument value passing it into the target method. Applicable only to VB Reference arguments. - + Information of the conversion applied to the argument value after the invocation. Applicable only to VB Reference arguments. - + Represents a catch clause. @@ -2058,15 +2060,14 @@ - - - Body of the exception handler. - - - + - Locals declared by the and/or clause. + Optional source for exception. This could be any of the following operation: + 1. Declaration for the local catch variable bound to the caught exception (C# and VB) OR + 2. Null, indicating no declaration or expression (C# and VB) + 3. Reference to an existing local or parameter (VB) OR + 4. Other expression for error scenarios (VB) @@ -2075,14 +2076,10 @@ Type of the exception handled by the catch clause. - + - Optional source for exception. This could be any of the following operation: - 1. Declaration for the local catch variable bound to the caught exception (C# and VB) OR - 2. Null, indicating no declaration or expression (C# and VB) - 3. Reference to an existing local or parameter (VB) OR - 4. Other expression for error scenarios (VB) + Locals declared by the and/or clause. @@ -2091,8 +2088,13 @@ Filter operation to be executed to determine whether to handle the exception. + + + Body of the exception handler. + + - + Represents a switch case section with one or more case clauses to match and one or more operations to execute within the section. @@ -2118,6 +2120,19 @@ Locals declared within the switch case section scoped to the section. + + + + Optional combined logical condition that accounts for all . + An instance of with kind + is used to refer to the in context of this expression. + It is not part of list and likely contains duplicate nodes for + nodes exposed by , like , + etc. + Never set for C# at the moment. + + + @@ -2155,7 +2170,7 @@ - + @@ -2185,7 +2200,7 @@ - + @@ -2247,7 +2262,7 @@ - + Represents a constituent part of an interpolated string. @@ -2276,7 +2291,7 @@ - + Represents a constituent interpolation part of an interpolated string operation. @@ -2367,7 +2382,7 @@ - + @@ -2418,7 +2433,7 @@ - + @@ -2433,7 +2448,7 @@ - + @@ -2473,7 +2488,7 @@ - + Represents that an intermediate result is being captured. @@ -2505,7 +2520,7 @@ - + Represents result of checking whether the is null. @@ -2563,7 +2578,7 @@ - + Represents a coalesce assignment operation with a target and a conditionally-evaluated value: @@ -2577,7 +2592,7 @@ - + Represents a range operation. @@ -2637,7 +2652,7 @@ - + Represents an individual clause of an to re-allocate storage space for a single array variable. @@ -2658,7 +2673,7 @@ - + Represents a C# recursive pattern. @@ -2702,7 +2717,7 @@ - + Represents a switch expression. @@ -2723,7 +2738,7 @@ - + Represents one arm of a switch expression. @@ -2748,7 +2763,7 @@ - + Represents an element of a property subpattern, which identifies a member to be matched and the @@ -2769,14 +2784,14 @@ - + Represents a standalone VB query Aggregate operation with more than one item in Into clause. - + Represents a C# fixed statement. @@ -2838,7 +2853,7 @@ - + Represents a of operations that are executed with implicit reference to the for member references. diff --git a/src/Compilers/Core/Portable/Operations/OperationNodes.cs b/src/Compilers/Core/Portable/Operations/OperationNodes.cs index 2edbf1bf40895..790c128be4c2d 100644 --- a/src/Compilers/Core/Portable/Operations/OperationNodes.cs +++ b/src/Compilers/Core/Portable/Operations/OperationNodes.cs @@ -1,8 +1,5 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -// Despite its name, this file IS NOT (yet) automatically generated. - -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -68,351 +65,341 @@ public override IEnumerable Children return _lazyChildrenInterlocked; } + } } - /// - /// Represents an operation that creates a pointer value by taking the address of a reference. - /// - internal abstract partial class BaseAddressOfOperation : Operation, IAddressOfOperation + internal abstract partial class BaseArgumentOperation { - protected BaseAddressOfOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.AddressOf, semanticModel, syntax, type, constantValue, isImplicit) + internal BaseArgumentOperation(ArgumentKind argumentKind, IParameterSymbol parameter, IConvertibleConversion inConversion, IConvertibleConversion outConversion, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(argumentKind, parameter, semanticModel, syntax, type, constantValue, isImplicit) { + InConversionConvertibleOpt = inConversion; + OutConversionConvertibleOpt = outConversion; } - public override IEnumerable Children - { - get - { - if (Reference != null) - { - yield return Reference; - } - } - } - /// - /// Addressed reference. - /// - public abstract IOperation Reference { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitAddressOf(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) + internal IConvertibleConversion InConversionConvertibleOpt { get; } + internal IConvertibleConversion OutConversionConvertibleOpt { get; } + public CommonConversion InConversion => InConversionConvertibleOpt?.ToCommonConversion() ?? Identity(); + public CommonConversion OutConversion => OutConversionConvertibleOpt?.ToCommonConversion() ?? Identity(); + + private static CommonConversion Identity() { - return visitor.VisitAddressOf(this, argument); + return new CommonConversion(exists: true, isIdentity: true, isNumeric: false, isReference: false, methodSymbol: null, isImplicit: true); } } - /// - /// Represents an operation that creates a pointer value by taking the address of a reference. - /// - internal sealed partial class AddressOfOperation : BaseAddressOfOperation, IAddressOfOperation + + internal sealed partial class ArgumentOperation { - public AddressOfOperation(IOperation reference, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public ArgumentOperation(IOperation value, ArgumentKind argumentKind, IParameterSymbol parameter, IConvertibleConversion inConversionOpt, IConvertibleConversion outConversionOpt, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : + base(argumentKind, parameter, inConversionOpt, outConversionOpt, semanticModel, syntax, type: null, constantValue: default, isImplicit) { - Reference = SetParentOperation(reference, this); + Value = SetParentOperation(value, this); } + } - public override IOperation Reference { get; } + + internal abstract partial class LazyArgumentOperation + { + public LazyArgumentOperation(ArgumentKind argumentKind, IConvertibleConversion inConversionOpt, IConvertibleConversion outConversionOpt, IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : + base(argumentKind, parameter, inConversionOpt, outConversionOpt, semanticModel, syntax, type: null, constantValue: default, isImplicit) + { } } - /// - /// Represents an operation that creates a pointer value by taking the address of a reference. - /// - internal abstract class LazyAddressOfOperation : BaseAddressOfOperation, IAddressOfOperation + + internal sealed partial class ArrayInitializerOperation : BaseArrayInitializerOperation, IArrayInitializerOperation { - private IOperation _lazyReferenceInterlocked = s_unset; + public ArrayInitializerOperation(ImmutableArray elementValues, SemanticModel semanticModel, SyntaxNode syntax, Optional constantValue, bool isImplicit) : + this(elementValues, semanticModel, syntax, type: null, constantValue, isImplicit) + { } - public LazyAddressOfOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + } + + internal abstract partial class BaseConversionOperation : Operation, IConversionOperation + { + public IMethodSymbol OperatorMethod => Conversion.MethodSymbol; + } + + internal abstract partial class BaseEventReferenceOperation + { + public override ISymbol Member => Event; + } + + internal sealed partial class VariableInitializerOperation : BaseVariableInitializerOperation, IVariableInitializerOperation + { + public VariableInitializerOperation(IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(ImmutableArray.Empty, value, semanticModel, syntax, type, constantValue, isImplicit) + { } + } + + internal abstract partial class BaseFieldReferenceOperation + { + public override ISymbol Member => Field; + } + + internal abstract partial class BaseForEachLoopOperation : BaseLoopOperation, IForEachLoopOperation + { + public abstract ForEachLoopOperationInfo Info { get; } + } + + internal sealed partial class ForEachLoopOperation : BaseForEachLoopOperation, IForEachLoopOperation + { + public ForEachLoopOperation(ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, IOperation loopControlVariable, + IOperation collection, ImmutableArray nextVariables, IOperation body, ForEachLoopOperationInfo info, + SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(loopControlVariable, collection, nextVariables, LoopKind.ForEach, body, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) { + Info = info; } - protected abstract IOperation CreateReference(); + public override ForEachLoopOperationInfo Info { get; } + } - public override IOperation Reference + internal abstract partial class LazyForEachLoopOperation : BaseForEachLoopOperation, IForEachLoopOperation + { + private ForEachLoopOperationInfo _lazyForEachLoopInfoInterlocked = null; + protected abstract ForEachLoopOperationInfo CreateLoopInfo(); + public override ForEachLoopOperationInfo Info { get { - if (_lazyReferenceInterlocked == s_unset) + if (_lazyForEachLoopInfoInterlocked == null) { - IOperation reference = CreateReference(); - SetParentOperation(reference, this); - Interlocked.CompareExchange(ref _lazyReferenceInterlocked, reference, s_unset); + Interlocked.CompareExchange(ref _lazyForEachLoopInfoInterlocked, CreateLoopInfo(), null); } - return _lazyReferenceInterlocked; + return _lazyForEachLoopInfoInterlocked; } } } - /// - /// Represents C# nameof and VB NameOf expression. - /// - internal abstract partial class BaseNameOfOperation : Operation, INameOfOperation + internal sealed partial class ForLoopOperation : BaseForLoopOperation, IForLoopOperation { - protected BaseNameOfOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.NameOf, semanticModel, syntax, type, constantValue, isImplicit) - { - } + public ForLoopOperation(ImmutableArray before, IOperation condition, ImmutableArray atLoopBottom, ImmutableArray locals, ImmutableArray conditionLocals, + ILabelSymbol continueLabel, ILabelSymbol exitLabel, IOperation body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(before, conditionLocals, condition, atLoopBottom, LoopKind.For, body, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + { } + } - public override IEnumerable Children + internal abstract partial class LazyForLoopOperation : BaseForLoopOperation, IForLoopOperation + { + public LazyForLoopOperation(ImmutableArray locals, ImmutableArray conditionLocals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(conditionLocals, LoopKind.For, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + { } + } + + internal sealed partial class ForToLoopOperation : BaseForToLoopOperation, IForToLoopOperation + { + public ForToLoopOperation(ImmutableArray locals, bool isChecked, + (ILocalSymbol LoopObject, ForToLoopOperationUserDefinedInfo UserDefinedInfo) info, + ILabelSymbol continueLabel, ILabelSymbol exitLabel, IOperation loopControlVariable, + IOperation initialValue, IOperation limitValue, IOperation stepValue, IOperation body, + ImmutableArray nextVariables, SemanticModel semanticModel, SyntaxNode syntax, + ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(loopControlVariable, initialValue, limitValue, stepValue, isChecked, nextVariables, info, LoopKind.ForTo, body, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + { } + } + + internal abstract partial class BaseInvalidOperation : Operation, IInvalidOperation + { + protected BaseInvalidOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(OperationKind.Invalid, semanticModel, syntax, type, constantValue, isImplicit) { - get - { - if (Argument != null) - { - yield return Argument; - } - } } - /// - /// Argument to name of expression. - /// - public abstract IOperation Argument { get; } - public override void Accept(OperationVisitor visitor) { - visitor.VisitNameOf(this); + visitor.VisitInvalid(this); } public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitNameOf(this, argument); + return visitor.VisitInvalid(this, argument); } } - /// - /// Represents C# nameof and VB NameOf expression. - /// - internal sealed partial class NameOfOperation : BaseNameOfOperation, INameOfOperation + + internal sealed partial class InvalidOperation : BaseInvalidOperation, IInvalidOperation { - public NameOfOperation(IOperation argument, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public InvalidOperation(ImmutableArray children, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(semanticModel, syntax, type, constantValue, isImplicit) { - Argument = SetParentOperation(argument, this); + // we don't allow null children. + Debug.Assert(children.All(o => o != null)); + Children = SetParentOperation(children, this); } - - public override IOperation Argument { get; } + public override IEnumerable Children { get; } } - /// - /// Represents C# nameof and VB NameOf expression. - /// - internal abstract class LazyNameOfOperation : BaseNameOfOperation, INameOfOperation + + internal abstract class LazyInvalidOperation : BaseInvalidOperation, IInvalidOperation { - private IOperation _lazyArgumentInterlocked = s_unset; + private ImmutableArray _lazyChildrenInterlocked; - public LazyNameOfOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public LazyInvalidOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(semanticModel, syntax, type, constantValue, isImplicit) { } - protected abstract IOperation CreateArgument(); + protected abstract ImmutableArray CreateChildren(); - public override IOperation Argument + public override IEnumerable Children { get { - if (_lazyArgumentInterlocked == s_unset) + if (_lazyChildrenInterlocked.IsDefault) { - IOperation argument = CreateArgument(); - SetParentOperation(argument, this); - Interlocked.CompareExchange(ref _lazyArgumentInterlocked, argument, s_unset); + ImmutableArray children = CreateChildren(); + SetParentOperation(children, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyChildrenInterlocked, children, default); } - return _lazyArgumentInterlocked; + return _lazyChildrenInterlocked; } } } - /// - /// Represents C# throw expression. - /// - internal abstract partial class BaseThrowOperation : Operation, IThrowOperation + internal sealed partial class SingleValueCaseClauseOperation : BaseSingleValueCaseClauseOperation, ISingleValueCaseClauseOperation + { + public SingleValueCaseClauseOperation(ILabelSymbol label, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(value, CaseKind.SingleValue, label, semanticModel, syntax, type, constantValue, isImplicit) + { } + } + + internal sealed class FlowAnonymousFunctionOperation : Operation, IFlowAnonymousFunctionOperation { - protected BaseThrowOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Throw, semanticModel, syntax, type, constantValue, isImplicit) + public readonly ControlFlowGraphBuilder.Context Context; + public readonly IAnonymousFunctionOperation Original; + + public FlowAnonymousFunctionOperation(in ControlFlowGraphBuilder.Context context, IAnonymousFunctionOperation original, bool isImplicit) : + base(OperationKind.FlowAnonymousFunction, semanticModel: null, original.Syntax, original.Type, original.ConstantValue, isImplicit) { + Context = context; + Original = original; } - + public IMethodSymbol Symbol => Original.Symbol; public override IEnumerable Children { get { - if (Exception != null) - { - yield return Exception; - } + return ImmutableArray.Empty; } } - /// - /// Expression. - /// - public abstract IOperation Exception { get; } public override void Accept(OperationVisitor visitor) { - visitor.VisitThrow(this); + visitor.VisitFlowAnonymousFunction(this); } public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitThrow(this, argument); + return visitor.VisitFlowAnonymousFunction(this, argument); } } - /// - /// Represents C# throw expression. - /// - internal sealed partial class ThrowOperation : BaseThrowOperation, IThrowOperation + + internal abstract partial class BaseMemberReferenceOperation : Operation, IMemberReferenceOperation { - public ThrowOperation(IOperation exception, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Exception = SetParentOperation(exception, this); + public abstract ISymbol Member { get; } + } - } + internal abstract partial class BaseMethodReferenceOperation + { + public override ISymbol Member => Method; + } - public override IOperation Exception { get; } + internal abstract partial class BasePropertyReferenceOperation + { + public override ISymbol Member => Property; } - /// - /// Represents C# throw expression. - /// - internal abstract class LazyThrowOperation : BaseThrowOperation, IThrowOperation + + internal sealed partial class RangeCaseClauseOperation : BaseRangeCaseClauseOperation, IRangeCaseClauseOperation { - private IOperation _lazyExceptionInterlocked = s_unset; + public RangeCaseClauseOperation(IOperation minimumValue, IOperation maximumValue, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(minimumValue, maximumValue, CaseKind.Range, label: null, semanticModel, syntax, type, constantValue, isImplicit) + { } + } - public LazyThrowOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + internal sealed partial class RelationalCaseClauseOperation : BaseRelationalCaseClauseOperation, IRelationalCaseClauseOperation + { + public RelationalCaseClauseOperation(IOperation value, BinaryOperatorKind relation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(value, relation, CaseKind.Relational, label: null, semanticModel, syntax, type, constantValue, isImplicit) + { } + } + + internal sealed partial class DefaultCaseClauseOperation : BaseCaseClauseOperation + { + public DefaultCaseClauseOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(CaseKind.Default, label, semanticModel, syntax, type, constantValue, isImplicit) + { } + } + + internal abstract partial class BaseSwitchCaseOperation + { + /// + /// Optional combined logical condition that accounts for all . + /// An instance of with kind + /// is used to refer to the in context of this expression. + /// It is not part of list and likely contains duplicate nodes for + /// nodes exposed by , like , + /// etc. + /// Never set for C# at the moment. + /// + public abstract IOperation Condition { get; } + } + + internal sealed partial class SwitchCaseOperation : BaseSwitchCaseOperation, ISwitchCaseOperation + { + public SwitchCaseOperation(ImmutableArray locals, IOperation condition, ImmutableArray clauses, ImmutableArray body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(clauses, body, locals, semanticModel, syntax, type, constantValue, isImplicit) { + Condition = SetParentOperation(condition, null); } - protected abstract IOperation CreateException(); + public override IOperation Condition { get; } + } - public override IOperation Exception + internal abstract partial class LazySwitchCaseOperation + { + private IOperation _lazyConditionInterlocked = s_unset; + protected abstract IOperation CreateCondition(); + public override IOperation Condition { get { - if (_lazyExceptionInterlocked == s_unset) + if (_lazyConditionInterlocked == s_unset) { - IOperation exception = CreateException(); - SetParentOperation(exception, this); - Interlocked.CompareExchange(ref _lazyExceptionInterlocked, exception, s_unset); + IOperation condition = CreateCondition(); + SetParentOperation(condition, null); + Interlocked.CompareExchange(ref _lazyConditionInterlocked, condition, s_unset); } - return _lazyExceptionInterlocked; + return _lazyConditionInterlocked; } } } - /// - /// Represents an argument in a method invocation. - /// - internal abstract partial class BaseArgumentOperation : Operation, IArgumentOperation + internal abstract partial class HasDynamicArgumentsExpression : Operation { - protected BaseArgumentOperation(ArgumentKind argumentKind, IParameterSymbol parameter, IConvertibleConversion inConversionOpt, IConvertibleConversion outConversionOpt, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : - base(OperationKind.Argument, semanticModel, syntax, type: null, constantValue: default, isImplicit: isImplicit) + protected HasDynamicArgumentsExpression(OperationKind operationKind, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(operationKind, semanticModel, syntax, type, constantValue, isImplicit) { - ArgumentKind = argumentKind; - Parameter = parameter; - InConversionConvertibleOpt = inConversionOpt; - OutConversionConvertibleOpt = outConversionOpt; + ArgumentNames = argumentNames; + ArgumentRefKinds = argumentRefKinds; } - /// - /// Kind of argument. - /// - public ArgumentKind ArgumentKind { get; } - /// - /// Parameter the argument matches. - /// - public IParameterSymbol Parameter { get; } - internal IConvertibleConversion InConversionConvertibleOpt { get; } - internal IConvertibleConversion OutConversionConvertibleOpt { get; } - public CommonConversion InConversion => InConversionConvertibleOpt?.ToCommonConversion() ?? Identity(); - public CommonConversion OutConversion => OutConversionConvertibleOpt?.ToCommonConversion() ?? Identity(); + public ImmutableArray ArgumentNames { get; } + public ImmutableArray ArgumentRefKinds { get; } + public abstract ImmutableArray Arguments { get; } + } - private static CommonConversion Identity() + internal abstract partial class BaseDynamicObjectCreationOperation : HasDynamicArgumentsExpression, IDynamicObjectCreationOperation + { + public BaseDynamicObjectCreationOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(OperationKind.DynamicObjectCreation, argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) { - return new CommonConversion(exists: true, isIdentity: true, isNumeric: false, isReference: false, methodSymbol: null, isImplicit: true); } - public override IEnumerable Children { get { - if (Value != null) + foreach (var argument in Arguments) { - yield return Value; - } - } - } - /// - /// Value supplied for the argument. - /// - public abstract IOperation Value { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitArgument(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitArgument(this, argument); - } - } - - internal sealed partial class ArgumentOperation : BaseArgumentOperation - { - public ArgumentOperation(IOperation value, ArgumentKind argumentKind, IParameterSymbol parameter, IConvertibleConversion inConversionOpt, IConvertibleConversion outConversionOpt, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : - base(argumentKind, parameter, inConversionOpt, outConversionOpt, semanticModel, syntax, isImplicit) - { - Value = SetParentOperation(value, this); - } - - public override IOperation Value { get; } - } - - internal abstract class LazyArgumentOperation : BaseArgumentOperation - { - private IOperation _lazyValueInterlocked = s_unset; - - public LazyArgumentOperation(ArgumentKind argumentKind, IConvertibleConversion inConversionOpt, IConvertibleConversion outConversionOpt, IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : - base(argumentKind, parameter, inConversionOpt, outConversionOpt, semanticModel, syntax, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents the creation of an array instance. - /// - internal abstract partial class BaseArrayCreationOperation : Operation, IArrayCreationOperation - { - protected BaseArrayCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.ArrayCreation, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override IEnumerable Children - { - get - { - foreach (var dimensionSize in DimensionSizes) - { - if (dimensionSize != null) + if (argument != null) { - yield return dimensionSize; + yield return argument; } } if (Initializer != null) @@ -421,80 +408,66 @@ public override IEnumerable Children } } } - /// - /// Sizes of the dimensions of the created array instance. - /// - public abstract ImmutableArray DimensionSizes { get; } - /// - /// Values of elements of the created array instance. - /// - public abstract IArrayInitializerOperation Initializer { get; } + public abstract IObjectOrCollectionInitializerOperation Initializer { get; } public override void Accept(OperationVisitor visitor) { - visitor.VisitArrayCreation(this); + visitor.VisitDynamicObjectCreation(this); } public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitArrayCreation(this, argument); + return visitor.VisitDynamicObjectCreation(this, argument); } } - /// - /// Represents the creation of an array instance. - /// - internal sealed partial class ArrayCreationOperation : BaseArrayCreationOperation, IArrayCreationOperation + internal sealed partial class DynamicObjectCreationOperation : BaseDynamicObjectCreationOperation, IDynamicObjectCreationOperation { - public ArrayCreationOperation(ImmutableArray dimensionSizes, IArrayInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public DynamicObjectCreationOperation(ImmutableArray arguments, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, IObjectOrCollectionInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) { - DimensionSizes = SetParentOperation(dimensionSizes, this); + Arguments = SetParentOperation(arguments, this); Initializer = SetParentOperation(initializer, this); } - - public override ImmutableArray DimensionSizes { get; } - public override IArrayInitializerOperation Initializer { get; } + public override ImmutableArray Arguments { get; } + public override IObjectOrCollectionInitializerOperation Initializer { get; } } - /// - /// Represents the creation of an array instance. - /// - internal abstract class LazyArrayCreationOperation : BaseArrayCreationOperation, IArrayCreationOperation + internal abstract class LazyDynamicObjectCreationOperation : BaseDynamicObjectCreationOperation, IDynamicObjectCreationOperation { - private ImmutableArray _lazyDimensionSizesInterlocked; - private IArrayInitializerOperation _lazyInitializerInterlocked = s_unsetArrayInitializer; + private ImmutableArray _lazyArgumentsInterlocked; + private IObjectOrCollectionInitializerOperation _lazyInitializerInterlocked = s_unsetObjectOrCollectionInitializer; - public LazyArrayCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public LazyDynamicObjectCreationOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) { } - protected abstract ImmutableArray CreateDimensionSizes(); - protected abstract IArrayInitializerOperation CreateInitializer(); + protected abstract ImmutableArray CreateArguments(); + protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); - public override ImmutableArray DimensionSizes + public override ImmutableArray Arguments { get { - if (_lazyDimensionSizesInterlocked.IsDefault) + if (_lazyArgumentsInterlocked.IsDefault) { - ImmutableArray dimensionSizes = CreateDimensionSizes(); - SetParentOperation(dimensionSizes, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDimensionSizesInterlocked, dimensionSizes, default); + ImmutableArray arguments = CreateArguments(); + SetParentOperation(arguments, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); } - return _lazyDimensionSizesInterlocked; + return _lazyArgumentsInterlocked; } } - public override IArrayInitializerOperation Initializer + public override IObjectOrCollectionInitializerOperation Initializer { get { - if (_lazyInitializerInterlocked == s_unsetArrayInitializer) + if (_lazyInitializerInterlocked == s_unsetObjectOrCollectionInitializer) { - IArrayInitializerOperation initializer = CreateInitializer(); + IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); SetParentOperation(initializer, this); - Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unsetArrayInitializer); + Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unsetObjectOrCollectionInitializer); } return _lazyInitializerInterlocked; @@ -502,8449 +475,278 @@ public override IArrayInitializerOperation Initializer } } - /// - /// Represents a reference to an array element. - /// - internal abstract partial class BaseArrayElementReferenceOperation : Operation, IArrayElementReferenceOperation + internal abstract partial class BaseDynamicInvocationOperation : HasDynamicArgumentsExpression, IDynamicInvocationOperation { - protected BaseArrayElementReferenceOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.ArrayElementReference, semanticModel, syntax, type, constantValue, isImplicit) + public BaseDynamicInvocationOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(OperationKind.DynamicInvocation, argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children { get { - if (ArrayReference != null) + if (Operation != null) { - yield return ArrayReference; + yield return Operation; } - - foreach (var index in Indices) + foreach (var argument in Arguments) { - if (index != null) + if (argument != null) { - yield return index; + yield return argument; } } } } - /// - /// Array to be indexed. - /// - public abstract IOperation ArrayReference { get; } - /// - /// Indices that specify an individual element. - /// - public abstract ImmutableArray Indices { get; } + public abstract IOperation Operation { get; } public override void Accept(OperationVisitor visitor) { - visitor.VisitArrayElementReference(this); + visitor.VisitDynamicInvocation(this); } public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitArrayElementReference(this, argument); + return visitor.VisitDynamicInvocation(this, argument); } } - /// - /// Represents a reference to an array element. - /// - internal sealed partial class ArrayElementReferenceOperation : BaseArrayElementReferenceOperation, IArrayElementReferenceOperation + internal sealed partial class DynamicInvocationOperation : BaseDynamicInvocationOperation, IDynamicInvocationOperation { - public ArrayElementReferenceOperation(IOperation arrayReference, ImmutableArray indices, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public DynamicInvocationOperation(IOperation operation, ImmutableArray arguments, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) { - ArrayReference = SetParentOperation(arrayReference, this); - Indices = SetParentOperation(indices, this); + Operation = SetParentOperation(operation, this); + Arguments = SetParentOperation(arguments, this); } - - public override IOperation ArrayReference { get; } - public override ImmutableArray Indices { get; } + public override IOperation Operation { get; } + public override ImmutableArray Arguments { get; } } - /// - /// Represents a reference to an array element. - /// - internal abstract class LazyArrayElementReferenceOperation : BaseArrayElementReferenceOperation, IArrayElementReferenceOperation + internal abstract class LazyDynamicInvocationOperation : BaseDynamicInvocationOperation, IDynamicInvocationOperation { - private IOperation _lazyArrayReferenceInterlocked = s_unset; - private ImmutableArray _lazyIndicesInterlocked; + private IOperation _lazyOperationInterlocked = s_unset; + private ImmutableArray _lazyArgumentsInterlocked; - public LazyArrayElementReferenceOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public LazyDynamicInvocationOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) { } - protected abstract IOperation CreateArrayReference(); - protected abstract ImmutableArray CreateIndices(); + protected abstract IOperation CreateOperation(); + protected abstract ImmutableArray CreateArguments(); - public override IOperation ArrayReference + public override IOperation Operation { get { - if (_lazyArrayReferenceInterlocked == s_unset) + if (_lazyOperationInterlocked == s_unset) { - IOperation arrayReference = CreateArrayReference(); - SetParentOperation(arrayReference, this); - Interlocked.CompareExchange(ref _lazyArrayReferenceInterlocked, arrayReference, s_unset); + IOperation operation = CreateOperation(); + SetParentOperation(operation, this); + Interlocked.CompareExchange(ref _lazyOperationInterlocked, operation, s_unset); } - return _lazyArrayReferenceInterlocked; + return _lazyOperationInterlocked; } } - public override ImmutableArray Indices + public override ImmutableArray Arguments { get { - if (_lazyIndicesInterlocked.IsDefault) + if (_lazyArgumentsInterlocked.IsDefault) { - ImmutableArray indices = CreateIndices(); - SetParentOperation(indices, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyIndicesInterlocked, indices, default); + ImmutableArray arguments = CreateArguments(); + SetParentOperation(arguments, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); } - return _lazyIndicesInterlocked; + return _lazyArgumentsInterlocked; } } } - /// - /// Represents the initialization of an array instance. - /// - internal abstract partial class BaseArrayInitializerOperation : Operation, IArrayInitializerOperation + internal abstract partial class BaseDynamicIndexerAccessOperation : HasDynamicArgumentsExpression, IDynamicIndexerAccessOperation { - protected BaseArrayInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, Optional constantValue, bool isImplicit) : - base(OperationKind.ArrayInitializer, semanticModel, syntax, type: null, constantValue: constantValue, isImplicit: isImplicit) + public BaseDynamicIndexerAccessOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(OperationKind.DynamicIndexerAccess, argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) { } - public override IEnumerable Children { get { - foreach (var elementValue in ElementValues) + if (Operation != null) + { + yield return Operation; + } + foreach (var argument in Arguments) { - if (elementValue != null) + if (argument != null) { - yield return elementValue; + yield return argument; } } } } - /// - /// Values to initialize array elements. - /// - public abstract ImmutableArray ElementValues { get; } + public abstract IOperation Operation { get; } public override void Accept(OperationVisitor visitor) { - visitor.VisitArrayInitializer(this); + visitor.VisitDynamicIndexerAccess(this); } public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitArrayInitializer(this, argument); + return visitor.VisitDynamicIndexerAccess(this, argument); } } - /// - /// Represents the initialization of an array instance. - /// - internal sealed partial class ArrayInitializerOperation : BaseArrayInitializerOperation, IArrayInitializerOperation + internal sealed partial class DynamicIndexerAccessOperation : BaseDynamicIndexerAccessOperation, IDynamicIndexerAccessOperation { - public ArrayInitializerOperation(ImmutableArray elementValues, SemanticModel semanticModel, SyntaxNode syntax, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, constantValue, isImplicit) + public DynamicIndexerAccessOperation(IOperation operation, ImmutableArray arguments, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) { - ElementValues = SetParentOperation(elementValues, this); + Operation = SetParentOperation(operation, this); + Arguments = SetParentOperation(arguments, this); } - - public override ImmutableArray ElementValues { get; } + public override IOperation Operation { get; } + public override ImmutableArray Arguments { get; } } - /// - /// Represents the initialization of an array instance. - /// - internal abstract class LazyArrayInitializerOperation : BaseArrayInitializerOperation, IArrayInitializerOperation + internal abstract class LazyDynamicIndexerAccessOperation : BaseDynamicIndexerAccessOperation, IDynamicIndexerAccessOperation { - private ImmutableArray _lazyElementValuesInterlocked; + private IOperation _lazyOperationInterlocked = s_unset; + private ImmutableArray _lazyArgumentsInterlocked; - public LazyArrayInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, constantValue, isImplicit) + public LazyDynamicIndexerAccessOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) { } - protected abstract ImmutableArray CreateElementValues(); + protected abstract IOperation CreateOperation(); + protected abstract ImmutableArray CreateArguments(); - public override ImmutableArray ElementValues + public override IOperation Operation { get { - if (_lazyElementValuesInterlocked.IsDefault) + if (_lazyOperationInterlocked == s_unset) { - ImmutableArray elementValues = CreateElementValues(); - SetParentOperation(elementValues, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyElementValuesInterlocked, elementValues, default); + IOperation operation = CreateOperation(); + SetParentOperation(operation, this); + Interlocked.CompareExchange(ref _lazyOperationInterlocked, operation, s_unset); } - return _lazyElementValuesInterlocked; + return _lazyOperationInterlocked; } } - } - /// - /// Represents an base type of assignment expression. - /// - internal abstract partial class AssignmentOperation : Operation, IAssignmentOperation - { - protected AssignmentOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) + public override ImmutableArray Arguments { + get + { + if (_lazyArgumentsInterlocked.IsDefault) + { + ImmutableArray arguments = CreateArguments(); + SetParentOperation(arguments, this); + ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); + } + + return _lazyArgumentsInterlocked; + } } - public sealed override IEnumerable Children + } + + internal abstract partial class BaseWhileLoopOperation : BaseLoopOperation, IWhileLoopOperation + { + public override IEnumerable Children { get { - if (Target != null) + if (ConditionIsTop) + { + if (Condition != null) + { + yield return Condition; + } + } + if (Body != null) + { + yield return Body; + } + if (!ConditionIsTop) { - yield return Target; + if (Condition != null) + { + yield return Condition; + } } - if (Value != null) + if (IgnoredCondition != null) { - yield return Value; + yield return IgnoredCondition; } } } - /// - /// Target of the assignment. - /// - public abstract IOperation Target { get; } - /// - /// Value to be assigned to the target of the assignment. - /// - public abstract IOperation Value { get; } } - /// - /// Represents a simple assignment expression. - /// - internal abstract partial class BaseSimpleAssignmentOperation : AssignmentOperation, ISimpleAssignmentOperation + internal sealed partial class WhileLoopOperation : BaseWhileLoopOperation, IWhileLoopOperation { - public BaseSimpleAssignmentOperation(bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.SimpleAssignment, semanticModel, syntax, type, constantValue, isImplicit) - { - IsRef = isRef; - } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitSimpleAssignment(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitSimpleAssignment(this, argument); - } + public WhileLoopOperation(IOperation condition, IOperation body, IOperation ignoredCondition, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, bool conditionIsTop, bool conditionIsUntil, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + this(condition, conditionIsTop, conditionIsUntil, ignoredCondition, LoopKind.While, body, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - /// - /// Is this a ref assignment - /// - public bool IsRef { get; } + { } } - /// - /// Represents a simple assignment expression. - /// - internal sealed partial class SimpleAssignmentOperation : BaseSimpleAssignmentOperation, ISimpleAssignmentOperation + internal sealed partial class ConstantPatternOperation : BaseConstantPatternOperation, IConstantPatternOperation { - public SimpleAssignmentOperation(IOperation target, bool isRef, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(isRef, semanticModel, syntax, type, constantValue, isImplicit) - { - Target = SetParentOperation(target, this); - Value = SetParentOperation(value, this); - } - public override IOperation Target { get; } - public override IOperation Value { get; } + public ConstantPatternOperation(ITypeSymbol inputType, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : + this(value, inputType, semanticModel, syntax, type: null, constantValue: default, isImplicit) + { } } - /// - /// Represents a simple assignment expression. - /// - internal abstract class LazySimpleAssignmentOperation : BaseSimpleAssignmentOperation, ISimpleAssignmentOperation + internal sealed partial class DeclarationPatternOperation : BasePatternOperation, IDeclarationPatternOperation { - private IOperation _lazyTargetInterlocked = s_unset; - private IOperation _lazyValueInterlocked = s_unset; - - public LazySimpleAssignmentOperation(bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(isRef, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateTarget(); - protected abstract IOperation CreateValue(); - - public override IOperation Target - { - get - { - if (_lazyTargetInterlocked == s_unset) - { - IOperation target = CreateTarget(); - SetParentOperation(target, this); - Interlocked.CompareExchange(ref _lazyTargetInterlocked, target, s_unset); - } - - return _lazyTargetInterlocked; - } - } - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents a deconstruction assignment expression. - /// - internal abstract partial class BaseDeconstructionAssignmentOperation : AssignmentOperation, IDeconstructionAssignmentOperation - { - public BaseDeconstructionAssignmentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.DeconstructionAssignment, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitDeconstructionAssignment(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitDeconstructionAssignment(this, argument); - } - } - - /// - /// Represents a deconstruction assignment expression. - /// - internal sealed partial class DeconstructionAssignmentOperation : BaseDeconstructionAssignmentOperation, IDeconstructionAssignmentOperation - { - public DeconstructionAssignmentOperation(IOperation target, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Target = SetParentOperation(target, this); - Value = SetParentOperation(value, this); - } - public override IOperation Target { get; } - public override IOperation Value { get; } - } - - /// - /// Represents a deconstruction assignment expression. - /// - internal abstract class LazyDeconstructionAssignmentOperation : BaseDeconstructionAssignmentOperation, IDeconstructionAssignmentOperation - { - private IOperation _lazyTargetInterlocked = s_unset; - private IOperation _lazyValueInterlocked = s_unset; - - public LazyDeconstructionAssignmentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateTarget(); - protected abstract IOperation CreateValue(); - - public override IOperation Target - { - get - { - if (_lazyTargetInterlocked == s_unset) - { - IOperation target = CreateTarget(); - SetParentOperation(target, this); - Interlocked.CompareExchange(ref _lazyTargetInterlocked, target, s_unset); - } - - return _lazyTargetInterlocked; - } - } - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents a declaration expression in C#. - /// Unlike a regular variable declaration, this operation represents an "expression" declaring a variable. - /// For example, - /// 1. "var (x, y)" is a deconstruction declaration expression with variables x and y. - /// 2. "(var x, var y)" is a tuple expression with two declaration expressions. - /// 3. "M(out var x);" is an invocation expression with an out "var x" declaration expression. - /// - internal abstract partial class BaseDeclarationExpressionOperation : Operation, IDeclarationExpressionOperation - { - public BaseDeclarationExpressionOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.DeclarationExpression, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override IEnumerable Children - { - get - { - if (Expression != null) - { - yield return Expression; - } - } - } - /// - /// Underlying expression. - /// - public abstract IOperation Expression { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitDeclarationExpression(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitDeclarationExpression(this, argument); - } - } - - /// - /// Represents a declaration expression in C#. - /// Unlike a regular variable declaration, this operation represents an "expression" declaring a variable. - /// For example, - /// 1. "var (x, y)" is a deconstruction declaration expression with variables x and y. - /// 2. "(var x, var y)" is a tuple expression with two declaration expressions. - /// 3. "M(out var x);" is an invocation expression with an out "var x" declaration expression. - /// - internal sealed partial class DeclarationExpressionOperation : BaseDeclarationExpressionOperation, IDeclarationExpressionOperation - { - public DeclarationExpressionOperation(IOperation expression, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Expression = SetParentOperation(expression, this); - } - public override IOperation Expression { get; } - } - - /// - /// Represents a declaration expression in C#. - /// Unlike a regular variable declaration, this operation represents an "expression" declaring a variable. - /// For example, - /// 1. "var (x, y)" is a deconstruction declaration expression with variables x and y. - /// 2. "(var x, var y)" is a tuple expression with two declaration expressions. - /// 3. "M(out var x);" is an invocation expression with an out "var x" declaration expression. - /// - internal abstract class LazyDeclarationExpressionOperation : BaseDeclarationExpressionOperation, IDeclarationExpressionOperation - { - private IOperation _lazyExpressionInterlocked = s_unset; - - public LazyDeclarationExpressionOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateExpression(); - - public override IOperation Expression - { - get - { - if (_lazyExpressionInterlocked == s_unset) - { - IOperation expression = CreateExpression(); - SetParentOperation(expression, this); - Interlocked.CompareExchange(ref _lazyExpressionInterlocked, expression, s_unset); - } - - return _lazyExpressionInterlocked; - } - } - } - - /// - /// Represents an await expression. - /// - internal abstract partial class BaseAwaitOperation : Operation, IAwaitOperation - { - protected BaseAwaitOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Await, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Operation != null) - { - yield return Operation; - } - } - } - /// - /// Awaited expression. - /// - public abstract IOperation Operation { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitAwait(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitAwait(this, argument); - } - } - - /// - /// Represents an await expression. - /// - internal sealed partial class AwaitOperation : BaseAwaitOperation, IAwaitOperation - { - public AwaitOperation(IOperation operation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Operation = SetParentOperation(operation, this); - } - - public override IOperation Operation { get; } - } - - /// - /// Represents an await expression. - /// - internal abstract class LazyAwaitOperation : BaseAwaitOperation, IAwaitOperation - { - private IOperation _lazyOperationInterlocked = s_unset; - - public LazyAwaitOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperation(); - - public override IOperation Operation - { - get - { - if (_lazyOperationInterlocked == s_unset) - { - IOperation operation = CreateOperation(); - SetParentOperation(operation, this); - Interlocked.CompareExchange(ref _lazyOperationInterlocked, operation, s_unset); - } - - return _lazyOperationInterlocked; - } - } - } - - /// - /// Represents an operation with two operands that produces a result with the same type as at least one of the operands. - /// - internal abstract partial class BaseBinaryOperation : Operation, IBinaryOperation - { - protected BaseBinaryOperation(BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, bool isCompareText, - IMethodSymbol operatorMethod, IMethodSymbol unaryOperatorMethod, SemanticModel semanticModel, - SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Binary, semanticModel, syntax, type, constantValue, isImplicit) - { - OperatorKind = operatorKind; - IsLifted = isLifted; - IsChecked = isChecked; - IsCompareText = isCompareText; - OperatorMethod = operatorMethod; - UnaryOperatorMethod = unaryOperatorMethod; - } - /// - /// Kind of binary operation. - /// - public BinaryOperatorKind OperatorKind { get; } - /// - /// Operator method used by the operation, null if the operation does not use an operator method. - /// - public IMethodSymbol OperatorMethod { get; } - - /// - /// True/False operator method used for short circuiting. - /// https://github.com/dotnet/roslyn/issues/27598 tracks exposing this information through public API - /// - public IMethodSymbol UnaryOperatorMethod { get; } - - /// - /// if this is a 'lifted' binary operator. When there is an - /// operator that is defined to work on a value type, 'lifted' operators are - /// created to work on the versions of those - /// value types. - /// - public bool IsLifted { get; } - /// - /// if overflow checking is performed for the arithmetic operation. - /// - public bool IsChecked { get; } - /// - /// if the comparison is text based for string or object comparison in VB. - /// - public bool IsCompareText { get; } - public override IEnumerable Children - { - get - { - if (LeftOperand != null) - { - yield return LeftOperand; - } - if (RightOperand != null) - { - yield return RightOperand; - } - } - } - /// - /// Left operand. - /// - public abstract IOperation LeftOperand { get; } - /// - /// Right operand. - /// - public abstract IOperation RightOperand { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitBinaryOperator(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitBinaryOperator(this, argument); - } - } - - /// - /// Represents an operation with two operands that produces a result with the same type as at least one of the operands. - /// - internal sealed partial class BinaryOperation : BaseBinaryOperation, IBinaryOperation - { - public BinaryOperation(BinaryOperatorKind operatorKind, IOperation leftOperand, IOperation rightOperand, bool isLifted, bool isChecked, bool isCompareText, - IMethodSymbol operatorMethod, IMethodSymbol unaryOperatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, - Optional constantValue, bool isImplicit) : - base(operatorKind, isLifted, isChecked, isCompareText, operatorMethod, unaryOperatorMethod, semanticModel, syntax, type, constantValue, isImplicit) - { - LeftOperand = SetParentOperation(leftOperand, this); - RightOperand = SetParentOperation(rightOperand, this); - } - - public override IOperation LeftOperand { get; } - public override IOperation RightOperand { get; } - } - - /// - /// Represents an operation with two operands that produces a result with the same type as at least one of the operands. - /// - internal abstract class LazyBinaryOperation : BaseBinaryOperation, IBinaryOperation - { - private IOperation _lazyLeftOperandInterlocked = s_unset; - private IOperation _lazyRightOperandInterlocked = s_unset; - - public LazyBinaryOperation(BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, bool isCompareText, IMethodSymbol operatorMethod, IMethodSymbol unaryOperatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(operatorKind, isLifted, isChecked, isCompareText, operatorMethod, unaryOperatorMethod, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateLeftOperand(); - protected abstract IOperation CreateRightOperand(); - - public override IOperation LeftOperand - { - get - { - if (_lazyLeftOperandInterlocked == s_unset) - { - IOperation leftOperand = CreateLeftOperand(); - SetParentOperation(leftOperand, this); - Interlocked.CompareExchange(ref _lazyLeftOperandInterlocked, leftOperand, s_unset); - } - - return _lazyLeftOperandInterlocked; - } - } - - public override IOperation RightOperand - { - get - { - if (_lazyRightOperandInterlocked == s_unset) - { - IOperation rightOperand = CreateRightOperand(); - SetParentOperation(rightOperand, this); - Interlocked.CompareExchange(ref _lazyRightOperandInterlocked, rightOperand, s_unset); - } - - return _lazyRightOperandInterlocked; - } - } - } - - /// - /// Represents an operation with two operands that produces a result with the same type as at least one of the operands. - /// - internal abstract class BaseTupleBinaryOperation : Operation, ITupleBinaryOperation - { - public BaseTupleBinaryOperation(BinaryOperatorKind operatorKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.TupleBinary, semanticModel, syntax, type, constantValue, isImplicit) - { - OperatorKind = operatorKind; - } - /// - /// Kind of binary operation. - /// - public BinaryOperatorKind OperatorKind { get; } - /// - /// Left operand. - /// - public abstract IOperation LeftOperand { get; } - /// - /// Right operand. - /// - public abstract IOperation RightOperand { get; } - - public override IEnumerable Children - { - get - { - if (LeftOperand != null) - { - yield return LeftOperand; - } - if (RightOperand != null) - { - yield return RightOperand; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitTupleBinaryOperator(this); - } - - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitTupleBinaryOperator(this, argument); - } - } - - /// - /// Represents an operation with two operands that produces a result with the same type as at least one of the operands. - /// - internal sealed class TupleBinaryOperation : BaseTupleBinaryOperation, ITupleBinaryOperation - { - public TupleBinaryOperation(BinaryOperatorKind operatorKind, IOperation leftOperand, IOperation rightOperand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(operatorKind, semanticModel, syntax, type, constantValue, isImplicit) - { - LeftOperand = SetParentOperation(leftOperand, this); - RightOperand = SetParentOperation(rightOperand, this); - } - - public override IOperation LeftOperand { get; } - public override IOperation RightOperand { get; } - } - - /// - /// Represents an operation with two operands that produces a result with the same type as at least one of the operands. - /// - internal abstract class LazyTupleBinaryOperation : BaseTupleBinaryOperation, ITupleBinaryOperation - { - private IOperation _lazyLeftOperandInterlocked = s_unset; - private IOperation _lazyRightOperandInterlocked = s_unset; - - public LazyTupleBinaryOperation(BinaryOperatorKind operatorKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(operatorKind, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateLeftOperand(); - protected abstract IOperation CreateRightOperand(); - - public override IOperation LeftOperand - { - get - { - if (_lazyLeftOperandInterlocked == s_unset) - { - IOperation leftOperand = CreateLeftOperand(); - SetParentOperation(leftOperand, this); - Interlocked.CompareExchange(ref _lazyLeftOperandInterlocked, leftOperand, s_unset); - } - - return _lazyLeftOperandInterlocked; - } - } - - public override IOperation RightOperand - { - get - { - if (_lazyRightOperandInterlocked == s_unset) - { - IOperation rightOperand = CreateRightOperand(); - SetParentOperation(rightOperand, this); - Interlocked.CompareExchange(ref _lazyRightOperandInterlocked, rightOperand, s_unset); - } - - return _lazyRightOperandInterlocked; - } - } - } - - /// - /// Represents a block scope. - /// - internal abstract partial class BaseBlockOperation : Operation, IBlockOperation - { - protected BaseBlockOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Block, semanticModel, syntax, type, constantValue, isImplicit) - { - Locals = locals; - } - - /// - /// Local declarations contained within the block. - /// - public ImmutableArray Locals { get; } - public override IEnumerable Children - { - get - { - foreach (var operation in Operations) - { - if (operation != null) - { - yield return operation; - } - } - } - } - /// - /// Statements contained within the block. - /// - public abstract ImmutableArray Operations { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitBlock(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitBlock(this, argument); - } - } - - /// - /// Represents a block scope. - /// - internal sealed partial class BlockOperation : BaseBlockOperation, IBlockOperation - { - public BlockOperation(ImmutableArray operations, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, semanticModel, syntax, type, constantValue, isImplicit) - { - Operations = SetParentOperation(operations, this); - } - - public override ImmutableArray Operations { get; } - } - - /// - /// Represents a block scope. - /// - internal abstract class LazyBlockOperation : BaseBlockOperation, IBlockOperation - { - private ImmutableArray _lazyOperationsInterlocked; - - public LazyBlockOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateOperations(); - - public override ImmutableArray Operations - { - get - { - if (_lazyOperationsInterlocked.IsDefault) - { - ImmutableArray operations = CreateOperations(); - SetParentOperation(operations, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyOperationsInterlocked, operations, default); - } - - return _lazyOperationsInterlocked; - } - } - } - - /// - /// Represents a clause of a C# case or a VB Case. - /// - internal abstract partial class BaseCaseClauseOperation : Operation, ICaseClauseOperation - { - protected BaseCaseClauseOperation(CaseKind caseKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - this(caseKind, label: null, OperationKind.CaseClause, semanticModel, syntax, type, constantValue, isImplicit) - { - } - } - - /// - /// Represents a C# catch or VB Catch clause. - /// - internal abstract partial class BaseCatchClauseOperation : Operation, ICatchClauseOperation - { - protected BaseCatchClauseOperation(ITypeSymbol exceptionType, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.CatchClause, semanticModel, syntax, type, constantValue, isImplicit) - { - ExceptionType = exceptionType; - Locals = locals; - } - /// - /// Type of the exception handled by the catch clause. - /// - public ITypeSymbol ExceptionType { get; } - /// - /// Locals declared by the and/or clause. - /// - public ImmutableArray Locals { get; } - public override IEnumerable Children - { - get - { - if (ExceptionDeclarationOrExpression != null) - { - yield return ExceptionDeclarationOrExpression; - } - if (Filter != null) - { - yield return Filter; - } - if (Handler != null) - { - yield return Handler; - } - } - } - /// - /// Optional source for exception. This could be any of the following operation: - /// 1. Declaration for the local catch variable bound to the caught exception (C# and VB) OR - /// 2. Type expression for the caught expression type (C#) OR - /// 3. Null, indicating no expression (C#) - /// 4. Reference to an existing local or parameter (VB) OR - /// 5. An error expression (VB) - /// - public abstract IOperation ExceptionDeclarationOrExpression { get; } - /// - /// Filter expression to be executed to determine whether to handle the exception. - /// - public abstract IOperation Filter { get; } - /// - /// Body of the exception handler. - /// - public abstract IBlockOperation Handler { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitCatchClause(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitCatchClause(this, argument); - } - } - - /// - /// Represents a C# catch or VB Catch clause. - /// - internal sealed partial class CatchClauseOperation : BaseCatchClauseOperation, ICatchClauseOperation - { - public CatchClauseOperation(IOperation exceptionDeclarationOrExpression, ITypeSymbol exceptionType, ImmutableArray locals, IOperation filter, IBlockOperation handler, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(exceptionType, locals, semanticModel, syntax, type, constantValue, isImplicit) - { - ExceptionDeclarationOrExpression = SetParentOperation(exceptionDeclarationOrExpression, this); - Filter = SetParentOperation(filter, this); - Handler = SetParentOperation(handler, this); - } - - public override IBlockOperation Handler { get; } - public override IOperation Filter { get; } - public override IOperation ExceptionDeclarationOrExpression { get; } - } - - /// - /// Represents a C# catch or VB Catch clause. - /// - internal abstract class LazyCatchClauseOperation : BaseCatchClauseOperation, ICatchClauseOperation - { - private IOperation _lazyExceptionDeclarationOrExpressionInterlocked = s_unset; - private IOperation _lazyFilterInterlocked = s_unset; - private IBlockOperation _lazyHandlerInterlocked = s_unsetBlock; - - public LazyCatchClauseOperation(ITypeSymbol exceptionType, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(exceptionType, locals, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateExceptionDeclarationOrExpression(); - protected abstract IOperation CreateFilter(); - protected abstract IBlockOperation CreateHandler(); - - public override IOperation ExceptionDeclarationOrExpression - { - get - { - if (_lazyExceptionDeclarationOrExpressionInterlocked == s_unset) - { - IOperation exceptionDeclarationOrExpression = CreateExceptionDeclarationOrExpression(); - SetParentOperation(exceptionDeclarationOrExpression, this); - Interlocked.CompareExchange(ref _lazyExceptionDeclarationOrExpressionInterlocked, exceptionDeclarationOrExpression, s_unset); - } - - return _lazyExceptionDeclarationOrExpressionInterlocked; - } - } - - public override IOperation Filter - { - get - { - if (_lazyFilterInterlocked == s_unset) - { - IOperation filter = CreateFilter(); - SetParentOperation(filter, this); - Interlocked.CompareExchange(ref _lazyFilterInterlocked, filter, s_unset); - } - - return _lazyFilterInterlocked; - } - } - - public override IBlockOperation Handler - { - get - { - if (_lazyHandlerInterlocked == s_unsetBlock) - { - IBlockOperation handler = CreateHandler(); - SetParentOperation(handler, this); - Interlocked.CompareExchange(ref _lazyHandlerInterlocked, handler, s_unsetBlock); - } - - return _lazyHandlerInterlocked; - } - } - } - - /// - /// Represents an assignment expression that includes a binary operation. - /// - internal abstract partial class BaseCompoundAssignmentOperation : AssignmentOperation, ICompoundAssignmentOperation - { - protected BaseCompoundAssignmentOperation(IConvertibleConversion inConversionConvertible, IConvertibleConversion outConversionConvertible, BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.CompoundAssignment, semanticModel, syntax, type, constantValue, isImplicit) - { - OperatorKind = operatorKind; - IsLifted = isLifted; - IsChecked = isChecked; - OperatorMethod = operatorMethod; - InConversionConvertible = inConversionConvertible; - OutConversionConvertible = outConversionConvertible; - } - /// - /// Kind of binary operation. - /// - public BinaryOperatorKind OperatorKind { get; } - /// - /// if this assignment contains a 'lifted' binary operation. - /// - public bool IsLifted { get; } - /// - /// if overflow checking is performed for the arithmetic operation. - /// - public bool IsChecked { get; } - /// - /// Operator method used by the operation, null if the operation does not use an operator method. - /// - public IMethodSymbol OperatorMethod { get; } - internal IConvertibleConversion InConversionConvertible { get; } - internal IConvertibleConversion OutConversionConvertible { get; } - public CommonConversion InConversion => InConversionConvertible.ToCommonConversion(); - public CommonConversion OutConversion => OutConversionConvertible.ToCommonConversion(); - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitCompoundAssignment(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitCompoundAssignment(this, argument); - } - } - - internal sealed partial class CompoundAssignmentOperation : BaseCompoundAssignmentOperation - { - public CompoundAssignmentOperation(IOperation target, IOperation value, IConvertibleConversion inConversionConvertible, IConvertibleConversion outConversionConvertible, BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(inConversionConvertible, outConversionConvertible, operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) - { - Target = SetParentOperation(target, this); - Value = SetParentOperation(value, this); - } - - public override IOperation Target { get; } - public override IOperation Value { get; } - } - - internal abstract class LazyCompoundAssignmentOperation : BaseCompoundAssignmentOperation - { - private IOperation _lazyTargetInterlocked = s_unset; - private IOperation _lazyValueInterlocked = s_unset; - - public LazyCompoundAssignmentOperation(IConvertibleConversion inConversionConvertible, IConvertibleConversion outConversionConvertible, BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(inConversionConvertible, outConversionConvertible, operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateTarget(); - protected abstract IOperation CreateValue(); - - public override IOperation Target - { - get - { - if (_lazyTargetInterlocked == s_unset) - { - IOperation target = CreateTarget(); - SetParentOperation(target, this); - Interlocked.CompareExchange(ref _lazyTargetInterlocked, target, s_unset); - } - - return _lazyTargetInterlocked; - } - } - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents an expression that includes a ? or ?. conditional access instance expression. - /// - internal abstract partial class BaseConditionalAccessOperation : Operation, IConditionalAccessOperation - { - protected BaseConditionalAccessOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.ConditionalAccess, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Operation != null) - { - yield return Operation; - } - if (WhenNotNull != null) - { - yield return WhenNotNull; - } - } - } - /// - /// Expression that is conditionally accessed. - /// - public abstract IOperation Operation { get; } - /// - /// Expression to be evaluated if the conditional instance is non null. - /// - public abstract IOperation WhenNotNull { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitConditionalAccess(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitConditionalAccess(this, argument); - } - } - - /// - /// Represents an expression that includes a ? or ?. conditional access instance expression. - /// - internal sealed partial class ConditionalAccessOperation : BaseConditionalAccessOperation, IConditionalAccessOperation - { - public ConditionalAccessOperation(IOperation whenNotNull, IOperation operation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - WhenNotNull = SetParentOperation(whenNotNull, this); - Operation = SetParentOperation(operation, this); - } - - public override IOperation Operation { get; } - public override IOperation WhenNotNull { get; } - } - - /// - /// Represents an expression that includes a ? or ?. conditional access instance expression. - /// - internal abstract class LazyConditionalAccessOperation : BaseConditionalAccessOperation, IConditionalAccessOperation - { - private IOperation _lazyWhenNotNullInterlocked = s_unset; - private IOperation _lazyOperationInterlocked = s_unset; - - public LazyConditionalAccessOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperation(); - protected abstract IOperation CreateWhenNotNull(); - - public override IOperation Operation - { - get - { - if (_lazyWhenNotNullInterlocked == s_unset) - { - IOperation operation = CreateOperation(); - SetParentOperation(operation, this); - Interlocked.CompareExchange(ref _lazyWhenNotNullInterlocked, operation, s_unset); - } - - return _lazyWhenNotNullInterlocked; - } - } - - public override IOperation WhenNotNull - { - get - { - if (_lazyOperationInterlocked == s_unset) - { - IOperation whenNotNull = CreateWhenNotNull(); - SetParentOperation(whenNotNull, this); - Interlocked.CompareExchange(ref _lazyOperationInterlocked, whenNotNull, s_unset); - } - - return _lazyOperationInterlocked; - } - } - } - - /// - /// Represents a conditional operation with: - /// 1. to be tested, - /// 2. operation to be executed when is true and - /// 3. operation to be executed when the is false. - /// For example, a C# ternary expression "a ? b : c" or a VB "If(a, b, c)" expression is represented as a conditional operation whose resulting value is the result of the expression. - /// Additionally, a C# "if else" statement or VB "If Then Else" is also is represented as a conditional operation, but with a dropped or no result value. - /// - internal abstract partial class BaseConditionalOperation : Operation, IConditionalOperation - { - protected BaseConditionalOperation(bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Conditional, semanticModel, syntax, type, constantValue, isImplicit) - { - IsRef = isRef; - } - public override IEnumerable Children - { - get - { - if (Condition != null) - { - yield return Condition; - } - if (WhenTrue != null) - { - yield return WhenTrue; - } - if (WhenFalse != null) - { - yield return WhenFalse; - } - } - } - /// - /// Condition to be tested. - /// - public abstract IOperation Condition { get; } - /// - /// Value evaluated if the Condition is true. - /// - public abstract IOperation WhenTrue { get; } - /// - /// Value evaluated if the Condition is false. - /// - public abstract IOperation WhenFalse { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitConditional(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitConditional(this, argument); - } - - /// - /// Is result a managed reference - /// - public bool IsRef { get; } - } - - /// - /// Represents a conditional operation with: - /// 1. to be tested, - /// 2. operation to be executed when is true and - /// 3. operation to be executed when the is false. - /// For example, a C# ternary expression "a ? b : c" or a VB "If(a, b, c)" expression is represented as a conditional operation whose resulting value is the result of the expression. - /// Additionally, a C# "if else" statement or VB "If Then Else" is also is represented as a conditional operation, but with a dropped or no result value. - /// - internal sealed partial class ConditionalOperation : BaseConditionalOperation, IConditionalOperation - { - public ConditionalOperation(IOperation condition, IOperation whenTrue, IOperation whenFalse, bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(isRef, semanticModel, syntax, type, constantValue, isImplicit) - { - Condition = SetParentOperation(condition, this); - WhenTrue = SetParentOperation(whenTrue, this); - WhenFalse = SetParentOperation(whenFalse, this); - } - - public override IOperation Condition { get; } - public override IOperation WhenTrue { get; } - public override IOperation WhenFalse { get; } - } - - /// - /// Represents a conditional operation with: - /// 1. to be tested, - /// 2. operation to be executed when is true and - /// 3. operation to be executed when the is false. - /// For example, a C# ternary expression "a ? b : c" or a VB "If(a, b, c)" expression is represented as a conditional operation whose resulting value is the result of the expression. - /// Additionally, a C# "if else" statement or VB "If Then Else" is also is represented as a conditional operation, but with a dropped or no result value. - /// - internal abstract class LazyConditionalOperation : BaseConditionalOperation, IConditionalOperation - { - private IOperation _lazyConditionInterlocked = s_unset; - private IOperation _lazyWhenTrueInterlocked = s_unset; - private IOperation _lazyWhenFalseInterlocked = s_unset; - - public LazyConditionalOperation(bool isRef, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(isRef, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateCondition(); - protected abstract IOperation CreateWhenTrue(); - protected abstract IOperation CreateWhenFalse(); - - public override IOperation Condition - { - get - { - if (_lazyConditionInterlocked == s_unset) - { - IOperation condition = CreateCondition(); - SetParentOperation(condition, this); - Interlocked.CompareExchange(ref _lazyConditionInterlocked, condition, s_unset); - } - - return _lazyConditionInterlocked; - } - } - - public override IOperation WhenTrue - { - get - { - if (_lazyWhenTrueInterlocked == s_unset) - { - IOperation whenTrue = CreateWhenTrue(); - SetParentOperation(whenTrue, this); - Interlocked.CompareExchange(ref _lazyWhenTrueInterlocked, whenTrue, s_unset); - } - - return _lazyWhenTrueInterlocked; - } - } - - public override IOperation WhenFalse - { - get - { - if (_lazyWhenFalseInterlocked == s_unset) - { - IOperation whenFalse = CreateWhenFalse(); - SetParentOperation(whenFalse, this); - Interlocked.CompareExchange(ref _lazyWhenFalseInterlocked, whenFalse, s_unset); - } - - return _lazyWhenFalseInterlocked; - } - } - } - - /// - /// Represents a conversion operation. - /// - internal abstract partial class BaseConversionOperation : Operation, IConversionOperation - { - protected BaseConversionOperation(IConvertibleConversion convertibleConversion, bool isTryCast, bool isChecked, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Conversion, semanticModel, syntax, type, constantValue, isImplicit) - { - IsTryCast = isTryCast; - IsChecked = isChecked; - ConvertibleConversion = convertibleConversion; - } - - internal IConvertibleConversion ConvertibleConversion { get; } - public CommonConversion Conversion => ConvertibleConversion.ToCommonConversion(); - public bool IsTryCast { get; } - public bool IsChecked { get; } - public IMethodSymbol OperatorMethod => Conversion.MethodSymbol; - public override IEnumerable Children - { - get - { - if (Operand != null) - { - yield return Operand; - } - } - } - /// - /// Value to be converted. - /// - public abstract IOperation Operand { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitConversion(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitConversion(this, argument); - } - } - - internal sealed partial class ConversionOperation : BaseConversionOperation - { - public ConversionOperation(IOperation operand, IConvertibleConversion convertibleConversion, bool isTryCast, bool isChecked, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(convertibleConversion, isTryCast, isChecked, semanticModel, syntax, type, constantValue, isImplicit) - { - Operand = SetParentOperation(operand, this); - } - - public override IOperation Operand { get; } - } - - internal abstract class LazyConversionOperation : BaseConversionOperation - { - private IOperation _lazyOperandInterlocked = s_unset; - - public LazyConversionOperation(IConvertibleConversion convertibleConversion, bool isTryCast, bool isChecked, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(convertibleConversion, isTryCast, isChecked, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperand(); - - public override IOperation Operand - { - get - { - if (_lazyOperandInterlocked == s_unset) - { - IOperation operand = CreateOperand(); - SetParentOperation(operand, this); - Interlocked.CompareExchange(ref _lazyOperandInterlocked, operand, s_unset); - } - - return _lazyOperandInterlocked; - } - } - } - - /// - /// Represents a binding of an event. - /// - internal abstract partial class BaseEventAssignmentOperation : Operation, IEventAssignmentOperation - { - protected BaseEventAssignmentOperation(bool adds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.EventAssignment, semanticModel, syntax, type, constantValue, isImplicit) - { - Adds = adds; - } - - /// - /// True for adding a binding, false for removing one. - /// - public bool Adds { get; } - public override IEnumerable Children - { - get - { - if (EventReference != null) - { - yield return EventReference; - } - if (HandlerValue != null) - { - yield return HandlerValue; - } - } - } - - /// - /// Instance used to refer to the event being bound. - /// - public abstract IOperation EventReference { get; } - - /// - /// Handler supplied for the event. - /// - public abstract IOperation HandlerValue { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitEventAssignment(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitEventAssignment(this, argument); - } - } - - /// - /// Represents a binding of an event. - /// - internal sealed partial class EventAssignmentOperation : BaseEventAssignmentOperation, IEventAssignmentOperation - { - public EventAssignmentOperation(IOperation eventReference, IOperation handlerValue, bool adds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(adds, semanticModel, syntax, type, constantValue, isImplicit) - { - EventReference = SetParentOperation(eventReference, this); - HandlerValue = SetParentOperation(handlerValue, this); - } - - public override IOperation EventReference { get; } - public override IOperation HandlerValue { get; } - } - - /// - /// Represents a binding of an event. - /// - internal abstract class LazyEventAssignmentOperation : BaseEventAssignmentOperation, IEventAssignmentOperation - { - private IOperation _lazyEventReferenceInterlocked = s_unset; - private IOperation _lazyHandlerValueInterlocked = s_unset; - - public LazyEventAssignmentOperation(bool adds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(adds, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateEventReference(); - protected abstract IOperation CreateHandlerValue(); - - public override IOperation EventReference - { - get - { - if (_lazyEventReferenceInterlocked == s_unset) - { - IOperation eventReference = CreateEventReference(); - SetParentOperation(eventReference, this); - Interlocked.CompareExchange(ref _lazyEventReferenceInterlocked, eventReference, s_unset); - } - - return _lazyEventReferenceInterlocked; - } - } - - public override IOperation HandlerValue - { - get - { - if (_lazyHandlerValueInterlocked == s_unset) - { - IOperation handlerValue = CreateHandlerValue(); - SetParentOperation(handlerValue, this); - Interlocked.CompareExchange(ref _lazyHandlerValueInterlocked, handlerValue, s_unset); - } - - return _lazyHandlerValueInterlocked; - } - } - } - - /// - /// Represents a reference to an event. - /// - internal abstract partial class BaseEventReferenceOperation : BaseMemberReferenceOperation, IEventReferenceOperation - { - public BaseEventReferenceOperation(IEventSymbol @event, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(@event, OperationKind.EventReference, semanticModel, syntax, type, constantValue, isImplicit) - { - } - /// - /// Referenced event. - /// - public IEventSymbol Event => (IEventSymbol)Member; - - public override IEnumerable Children - { - get - { - if (Instance != null) - { - yield return Instance; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitEventReference(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitEventReference(this, argument); - } - } - - /// - /// Represents a reference to an event. - /// - internal sealed partial class EventReferenceOperation : BaseEventReferenceOperation, IEventReferenceOperation - { - public EventReferenceOperation(IEventSymbol @event, IOperation instance, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(@event, semanticModel, syntax, type, constantValue, isImplicit) - { - Instance = SetParentOperation(instance, this); - } - public override IOperation Instance { get; } - } - - /// - /// Represents a reference to an event. - /// - internal abstract class LazyEventReferenceOperation : BaseEventReferenceOperation, IEventReferenceOperation - { - private IOperation _lazyInstanceInterlocked = s_unset; - - public LazyEventReferenceOperation(IEventSymbol @event, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(@event, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateInstance(); - - public override IOperation Instance - { - get - { - if (_lazyInstanceInterlocked == s_unset) - { - IOperation instance = CreateInstance(); - SetParentOperation(instance, this); - Interlocked.CompareExchange(ref _lazyInstanceInterlocked, instance, s_unset); - } - - return _lazyInstanceInterlocked; - } - } - } - - /// - /// Represents a C# or VB statement that consists solely of an expression. - /// - internal abstract partial class BaseExpressionStatementOperation : Operation, IExpressionStatementOperation - { - protected BaseExpressionStatementOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.ExpressionStatement, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Operation != null) - { - yield return Operation; - } - } - } - /// - /// Expression of the statement. - /// - public abstract IOperation Operation { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitExpressionStatement(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitExpressionStatement(this, argument); - } - } - - /// - /// Represents a C# or VB statement that consists solely of an expression. - /// - internal sealed partial class ExpressionStatementOperation : BaseExpressionStatementOperation, IExpressionStatementOperation - { - public ExpressionStatementOperation(IOperation operation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Operation = SetParentOperation(operation, this); - } - - public override IOperation Operation { get; } - } - - /// - /// Represents a C# or VB statement that consists solely of an expression. - /// - internal abstract class LazyExpressionStatementOperation : BaseExpressionStatementOperation, IExpressionStatementOperation - { - private IOperation _lazyOperationInterlocked = s_unset; - - public LazyExpressionStatementOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperation(); - - public override IOperation Operation - { - get - { - if (_lazyOperationInterlocked == s_unset) - { - IOperation operation = CreateOperation(); - SetParentOperation(operation, this); - Interlocked.CompareExchange(ref _lazyOperationInterlocked, operation, s_unset); - } - - return _lazyOperationInterlocked; - } - } - } - - /// - /// Represents an initialization of a local variable. - /// - internal abstract partial class BaseVariableInitializerOperation : SymbolInitializer, IVariableInitializerOperation - { - public BaseVariableInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.VariableInitializer, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitVariableInitializer(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitVariableInitializer(this, argument); - } - - ImmutableArray ISymbolInitializerOperation.Locals => ImmutableArray.Empty; - } - - /// - /// Represents an initialization of a local variable. - /// - internal sealed partial class VariableInitializerOperation : BaseVariableInitializerOperation, IVariableInitializerOperation - { - public VariableInitializerOperation(IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Value = SetParentOperation(value, this); - } - public override IOperation Value { get; } - } - - /// - /// Represents an initialization of a local variable. - /// - internal abstract class LazyVariableInitializerOperation : BaseVariableInitializerOperation, IVariableInitializerOperation - { - private IOperation _lazyValueInterlocked = s_unset; - - public LazyVariableInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents an initialization of a field. - /// - internal abstract partial class BaseFieldInitializerOperation : SymbolInitializer, IFieldInitializerOperation - { - public BaseFieldInitializerOperation(ImmutableArray locals, ImmutableArray initializedFields, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) - { - Locals = locals; - InitializedFields = initializedFields; - } - - public ImmutableArray Locals { get; } - - /// - /// Initialized fields. There can be multiple fields for Visual Basic fields declared with As New. - /// - public ImmutableArray InitializedFields { get; } - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitFieldInitializer(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitFieldInitializer(this, argument); - } - } - - /// - /// Represents an initialization of a field. - /// - internal sealed partial class FieldInitializerOperation : BaseFieldInitializerOperation, IFieldInitializerOperation - { - public FieldInitializerOperation(ImmutableArray locals, ImmutableArray initializedFields, IOperation value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, initializedFields, kind, semanticModel, syntax, type, constantValue, isImplicit) - { - Value = SetParentOperation(value, this); - } - public override IOperation Value { get; } - } - - /// - /// Represents an initialization of a field. - /// - internal abstract class LazyFieldInitializerOperation : BaseFieldInitializerOperation, IFieldInitializerOperation - { - private IOperation _lazyValueInterlocked = s_unset; - - public LazyFieldInitializerOperation(ImmutableArray locals, ImmutableArray initializedFields, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, initializedFields, kind, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents a reference to a field. - /// - internal abstract partial class BaseFieldReferenceOperation : BaseMemberReferenceOperation, IFieldReferenceOperation - { - public BaseFieldReferenceOperation(IFieldSymbol field, bool isDeclaration, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(field, OperationKind.FieldReference, semanticModel, syntax, type, constantValue, isImplicit) - { - IsDeclaration = isDeclaration; - } - /// - /// Referenced field. - /// - public IFieldSymbol Field => (IFieldSymbol)Member; - public bool IsDeclaration { get; } - public override IEnumerable Children - { - get - { - if (Instance != null) - { - yield return Instance; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitFieldReference(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitFieldReference(this, argument); - } - } - - /// - /// Represents a reference to a field. - /// - internal sealed partial class FieldReferenceOperation : BaseFieldReferenceOperation, IFieldReferenceOperation - { - public FieldReferenceOperation(IFieldSymbol field, bool isDeclaration, IOperation instance, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(field, isDeclaration, semanticModel, syntax, type, constantValue, isImplicit) - { - Instance = SetParentOperation(instance, this); - } - public override IOperation Instance { get; } - } - - /// - /// Represents a reference to a field. - /// - internal abstract class LazyFieldReferenceOperation : BaseFieldReferenceOperation, IFieldReferenceOperation - { - private IOperation _lazyInstanceInterlocked = s_unset; - - public LazyFieldReferenceOperation(IFieldSymbol field, bool isDeclaration, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(field, isDeclaration, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateInstance(); - - public override IOperation Instance - { - get - { - if (_lazyInstanceInterlocked == s_unset) - { - IOperation instance = CreateInstance(); - SetParentOperation(instance, this); - Interlocked.CompareExchange(ref _lazyInstanceInterlocked, instance, s_unset); - } - - return _lazyInstanceInterlocked; - } - } - } - - /// - /// Represents a C# fixed statement. - /// - internal abstract partial class BaseFixedOperation : Operation, IFixedOperation - { - protected BaseFixedOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - // https://github.com/dotnet/roslyn/issues/21281 - // base(OperationKind.Fixed, semanticModel, syntax, type, constantValue) - base(OperationKind.None, semanticModel, syntax, type, constantValue, isImplicit) - { - Locals = locals; - } - - public override IEnumerable Children - { - get - { - if (Variables != null) - { - yield return Variables; - } - if (Body != null) - { - yield return Body; - } - } - } - - public ImmutableArray Locals { get; } - - /// - /// Variables to be fixed. - /// - public abstract IVariableDeclarationGroupOperation Variables { get; } - /// - /// Body of the fixed, over which the variables are fixed. - /// - public abstract IOperation Body { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitFixed(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitFixed(this, argument); - } - } - - /// - /// Represents a C# fixed statement. - /// - internal sealed partial class FixedOperation : BaseFixedOperation, IFixedOperation - { - public FixedOperation(ImmutableArray locals, IVariableDeclarationGroupOperation variables, IOperation body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, semanticModel, syntax, type, constantValue, isImplicit) - { - Variables = SetParentOperation(variables, this); - Body = SetParentOperation(body, this); - } - - public override IVariableDeclarationGroupOperation Variables { get; } - public override IOperation Body { get; } - } - - /// - /// Represents a C# fixed statement. - /// - internal abstract class LazyFixedOperation : BaseFixedOperation, IFixedOperation - { - private IVariableDeclarationGroupOperation _lazyVariablesInterlocked = s_unsetVariableDeclarationGroup; - private IOperation _lazyBodyInterlocked = s_unset; - - public LazyFixedOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IVariableDeclarationGroupOperation CreateVariables(); - protected abstract IOperation CreateBody(); - - public override IVariableDeclarationGroupOperation Variables - { - get - { - if (_lazyVariablesInterlocked == s_unsetVariableDeclarationGroup) - { - IVariableDeclarationGroupOperation variables = CreateVariables(); - SetParentOperation(variables, this); - Interlocked.CompareExchange(ref _lazyVariablesInterlocked, variables, s_unsetVariableDeclarationGroup); - } - - return _lazyVariablesInterlocked; - } - } - - public override IOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unset) - { - IOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unset); - } - - return _lazyBodyInterlocked; - } - } - } - - /// - /// Represents a C# 'foreach' statement or a VB 'For Each' statement. - /// - internal abstract partial class BaseForEachLoopOperation : LoopOperation, IForEachLoopOperation - { - public BaseForEachLoopOperation(ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(LoopKind.ForEach, locals, continueLabel, exitLabel, OperationKind.Loop, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Collection != null) - { - yield return Collection; - } - if (LoopControlVariable != null) - { - yield return LoopControlVariable; - } - if (Body != null) - { - yield return Body; - } - foreach (var expression in NextVariables) - { - if (expression != null) - { - yield return expression; - } - } - } - } - - public abstract ForEachLoopOperationInfo Info { get; } - - /// - /// Optional loop control variable in VB that refers to the operation for declaring a new local variable or reference an existing variable or an expression. - /// This field is always null for C#. - /// - public abstract IOperation LoopControlVariable { get; } - /// - /// Collection value over which the loop iterates. - /// - public abstract IOperation Collection { get; } - /// - /// Optional list of comma separate operations to execute at loop bottom for VB. - /// This list is always empty for C#. - /// - public abstract ImmutableArray NextVariables { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitForEachLoop(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitForEachLoop(this, argument); - } - } - - /// - /// Represents a C# 'foreach' statement or a VB 'For Each' statement. - /// - internal sealed partial class ForEachLoopOperation : BaseForEachLoopOperation, IForEachLoopOperation - { - public ForEachLoopOperation(ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, IOperation loopControlVariable, - IOperation collection, ImmutableArray nextVariables, IOperation body, ForEachLoopOperationInfo info, - SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - LoopControlVariable = SetParentOperation(loopControlVariable, this); - Collection = SetParentOperation(collection, this); - NextVariables = SetParentOperation(nextVariables, this); - Body = SetParentOperation(body, this); - Info = info; - } - - public override ForEachLoopOperationInfo Info { get; } - public override IOperation LoopControlVariable { get; } - public override IOperation Collection { get; } - public override ImmutableArray NextVariables { get; } - public override IOperation Body { get; } - } - - /// - /// Represents a C# 'foreach' statement or a VB 'For Each' statement. - /// - internal abstract class LazyForEachLoopOperation : BaseForEachLoopOperation, IForEachLoopOperation - { - private ForEachLoopOperationInfo _lazyForEachLoopInfoInterlocked = null; - private IOperation _lazyLoopControlVariableInterlocked = s_unset; - private IOperation _lazyCollectionInterlocked = s_unset; - private ImmutableArray _lazyNextVariablesInterlocked; - private IOperation _lazyBodyInterlocked = s_unset; - - public LazyForEachLoopOperation(ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ForEachLoopOperationInfo CreateLoopInfo(); - protected abstract IOperation CreateLoopControlVariable(); - protected abstract IOperation CreateCollection(); - protected abstract ImmutableArray CreateNextVariables(); - protected abstract IOperation CreateBody(); - - public override ForEachLoopOperationInfo Info - { - get - { - if (_lazyForEachLoopInfoInterlocked == null) - { - Interlocked.CompareExchange(ref _lazyForEachLoopInfoInterlocked, CreateLoopInfo(), null); - } - - return _lazyForEachLoopInfoInterlocked; - } - } - - public override IOperation LoopControlVariable - { - get - { - if (_lazyLoopControlVariableInterlocked == s_unset) - { - IOperation loopControlVariable = CreateLoopControlVariable(); - SetParentOperation(loopControlVariable, this); - Interlocked.CompareExchange(ref _lazyLoopControlVariableInterlocked, loopControlVariable, s_unset); - } - - return _lazyLoopControlVariableInterlocked; - } - } - - public override IOperation Collection - { - get - { - if (_lazyCollectionInterlocked == s_unset) - { - IOperation collection = CreateCollection(); - SetParentOperation(collection, this); - Interlocked.CompareExchange(ref _lazyCollectionInterlocked, collection, s_unset); - } - - return _lazyCollectionInterlocked; - } - } - - public override ImmutableArray NextVariables - { - get - { - if (_lazyNextVariablesInterlocked.IsDefault) - { - ImmutableArray nextVariables = CreateNextVariables(); - SetParentOperation(nextVariables, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyNextVariablesInterlocked, nextVariables, default); - } - - return _lazyNextVariablesInterlocked; - } - } - - public override IOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unset) - { - IOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unset); - } - - return _lazyBodyInterlocked; - } - } - } - - /// - /// Represents a C# 'for' loop statement. - /// - internal abstract partial class BaseForLoopOperation : LoopOperation, IForLoopOperation - { - public BaseForLoopOperation(ImmutableArray locals, ImmutableArray conditionLocals, - ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, - SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(LoopKind.For, locals, continueLabel, exitLabel, OperationKind.Loop, semanticModel, syntax, type, constantValue, isImplicit) - { - ConditionLocals = conditionLocals; - } - - public ImmutableArray ConditionLocals { get; } - - public override IEnumerable Children - { - get - { - foreach (var before in Before) - { - if (before != null) - { - yield return before; - } - } - if (Condition != null) - { - yield return Condition; - } - if (Body != null) - { - yield return Body; - } - foreach (var atLoopBottom in AtLoopBottom) - { - if (atLoopBottom != null) - { - yield return atLoopBottom; - } - } - } - } - /// - /// List of operations to execute before entry to the loop. This comes from the first clause of the for statement. - /// - public abstract ImmutableArray Before { get; } - /// - /// Condition of the loop. This comes from the second clause of the for statement. - /// - public abstract IOperation Condition { get; } - /// - /// List of operations to execute at the bottom of the loop. This comes from the third clause of the for statement. - /// - public abstract ImmutableArray AtLoopBottom { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitForLoop(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitForLoop(this, argument); - } - } - - /// - /// Represents a C# 'for' loop statement. - /// - internal sealed partial class ForLoopOperation : BaseForLoopOperation, IForLoopOperation - { - public ForLoopOperation(ImmutableArray before, IOperation condition, ImmutableArray atLoopBottom, ImmutableArray locals, ImmutableArray conditionLocals, - ILabelSymbol continueLabel, ILabelSymbol exitLabel, IOperation body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, conditionLocals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - Before = SetParentOperation(before, this); - Condition = SetParentOperation(condition, this); - AtLoopBottom = SetParentOperation(atLoopBottom, this); - Body = SetParentOperation(body, this); - } - - public override ImmutableArray Before { get; } - public override IOperation Condition { get; } - public override ImmutableArray AtLoopBottom { get; } - public override IOperation Body { get; } - } - - /// - /// Represents a C# 'for' loop statement. - /// - internal abstract class LazyForLoopOperation : BaseForLoopOperation, IForLoopOperation - { - private ImmutableArray _lazyBeforeInterlocked; - private IOperation _lazyConditionInterlocked = s_unset; - private ImmutableArray _lazyAtLoopBottomInterlocked; - private IOperation _lazyBodyInterlocked = s_unset; - - public LazyForLoopOperation(ImmutableArray locals, ImmutableArray conditionLocals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, conditionLocals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateBefore(); - protected abstract IOperation CreateCondition(); - protected abstract ImmutableArray CreateAtLoopBottom(); - protected abstract IOperation CreateBody(); - - public override ImmutableArray Before - { - get - { - if (_lazyBeforeInterlocked.IsDefault) - { - ImmutableArray before = CreateBefore(); - SetParentOperation(before, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyBeforeInterlocked, before, default); - } - - return _lazyBeforeInterlocked; - } - } - - public override IOperation Condition - { - get - { - if (_lazyConditionInterlocked == s_unset) - { - IOperation condition = CreateCondition(); - SetParentOperation(condition, this); - Interlocked.CompareExchange(ref _lazyConditionInterlocked, condition, s_unset); - } - - return _lazyConditionInterlocked; - } - } - - public override ImmutableArray AtLoopBottom - { - get - { - if (_lazyAtLoopBottomInterlocked.IsDefault) - { - ImmutableArray atLoopBottom = CreateAtLoopBottom(); - SetParentOperation(atLoopBottom, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyAtLoopBottomInterlocked, atLoopBottom, default); - } - - return _lazyAtLoopBottomInterlocked; - } - } - - public override IOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unset) - { - IOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unset); - } - - return _lazyBodyInterlocked; - } - } - } - - /// - /// Represents a VB 'For To' loop statement. - /// - internal abstract partial class BaseForToLoopOperation : LoopOperation, IForToLoopOperation - { - public BaseForToLoopOperation(ImmutableArray locals, bool isChecked, - (ILocalSymbol LoopObject, ForToLoopOperationUserDefinedInfo UserDefinedInfo) info, - ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(LoopKind.ForTo, locals, continueLabel, exitLabel, OperationKind.Loop, semanticModel, syntax, type, constantValue, isImplicit) - { - Debug.Assert(info.LoopObject == null || info.LoopObject.Type.SpecialType == SpecialType.System_Object); - - IsChecked = isChecked; - Info = info; - } - - public bool IsChecked { get; } - - public (ILocalSymbol LoopObject, ForToLoopOperationUserDefinedInfo UserDefinedInfo) Info { get; } - - public override IEnumerable Children - { - get - { - if (LoopControlVariable != null) - { - yield return LoopControlVariable; - } - if (InitialValue != null) - { - yield return InitialValue; - } - if (LimitValue != null) - { - yield return LimitValue; - } - if (StepValue != null) - { - yield return StepValue; - } - if (Body != null) - { - yield return Body; - } - foreach (var expression in NextVariables) - { - if (expression != null) - { - yield return expression; - } - } - } - } - /// - /// Loop control variable refers to the operation for declaring a new local variable or reference an existing variable or an expression. - /// - public abstract IOperation LoopControlVariable { get; } - - /// - /// Operation for setting the initial value of the loop control variable. This comes from the expression between the 'For' and 'To' keywords. - /// - public abstract IOperation InitialValue { get; } - - /// - /// Operation for the limit value of the loop control variable. This comes from the expression after the 'To' keyword. - /// - public abstract IOperation LimitValue { get; } - - /// - /// Optional operation for the step value of the loop control variable. This comes from the expression after the 'Step' keyword. - /// - public abstract IOperation StepValue { get; } - - /// - /// Optional list of comma separated next variables at loop bottom. - /// - public abstract ImmutableArray NextVariables { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitForToLoop(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitForToLoop(this, argument); - } - } - - /// - /// Represents a VB 'For To' loop statement. - /// - internal sealed partial class ForToLoopOperation : BaseForToLoopOperation, IForToLoopOperation - { - public ForToLoopOperation(ImmutableArray locals, bool isChecked, - (ILocalSymbol LoopObject, ForToLoopOperationUserDefinedInfo UserDefinedInfo) info, - ILabelSymbol continueLabel, ILabelSymbol exitLabel, IOperation loopControlVariable, - IOperation initialValue, IOperation limitValue, IOperation stepValue, IOperation body, - ImmutableArray nextVariables, SemanticModel semanticModel, SyntaxNode syntax, - ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, isChecked, info, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - LoopControlVariable = SetParentOperation(loopControlVariable, this); - InitialValue = SetParentOperation(initialValue, this); - LimitValue = SetParentOperation(limitValue, this); - StepValue = SetParentOperation(stepValue, this); - Body = SetParentOperation(body, this); - NextVariables = SetParentOperation(nextVariables, this); - } - - public override IOperation LoopControlVariable { get; } - public override IOperation InitialValue { get; } - public override IOperation LimitValue { get; } - public override IOperation StepValue { get; } - public override IOperation Body { get; } - public override ImmutableArray NextVariables { get; } - } - - /// - /// Represents a VB 'For To' loop statement. - /// - internal abstract class LazyForToLoopOperation : BaseForToLoopOperation, IForToLoopOperation - { - private IOperation _lazyLoopControlVariableInterlocked = s_unset; - private IOperation _lazyInitialValueInterlocked = s_unset; - private IOperation _lazyLimitValueInterlocked = s_unset; - private IOperation _lazyStepValueInterlocked = s_unset; - private IOperation _lazyBodyInterlocked = s_unset; - private ImmutableArray _lazyNextVariablesInterlocked; - - public LazyForToLoopOperation(ImmutableArray locals, bool isChecked, (ILocalSymbol LoopObject, ForToLoopOperationUserDefinedInfo UserDefinedInfo) info, ILabelSymbol continueLabel, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, isChecked, info, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateLoopControlVariable(); - protected abstract IOperation CreateInitialValue(); - protected abstract IOperation CreateLimitValue(); - protected abstract IOperation CreateStepValue(); - protected abstract IOperation CreateBody(); - protected abstract ImmutableArray CreateNextVariables(); - - public override IOperation LoopControlVariable - { - get - { - if (_lazyLoopControlVariableInterlocked == s_unset) - { - IOperation loopControlVariable = CreateLoopControlVariable(); - SetParentOperation(loopControlVariable, this); - Interlocked.CompareExchange(ref _lazyLoopControlVariableInterlocked, loopControlVariable, s_unset); - } - - return _lazyLoopControlVariableInterlocked; - } - } - - public override IOperation InitialValue - { - get - { - if (_lazyInitialValueInterlocked == s_unset) - { - IOperation initialValue = CreateInitialValue(); - SetParentOperation(initialValue, this); - Interlocked.CompareExchange(ref _lazyInitialValueInterlocked, initialValue, s_unset); - } - - return _lazyInitialValueInterlocked; - } - } - - public override IOperation LimitValue - { - get - { - if (_lazyLimitValueInterlocked == s_unset) - { - IOperation limitValue = CreateLimitValue(); - SetParentOperation(limitValue, this); - Interlocked.CompareExchange(ref _lazyLimitValueInterlocked, limitValue, s_unset); - } - - return _lazyLimitValueInterlocked; - } - } - - public override IOperation StepValue - { - get - { - if (_lazyStepValueInterlocked == s_unset) - { - IOperation stepValue = CreateStepValue(); - SetParentOperation(stepValue, this); - Interlocked.CompareExchange(ref _lazyStepValueInterlocked, stepValue, s_unset); - } - - return _lazyStepValueInterlocked; - } - } - - public override IOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unset) - { - IOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unset); - } - - return _lazyBodyInterlocked; - } - } - - public override ImmutableArray NextVariables - { - get - { - if (_lazyNextVariablesInterlocked.IsDefault) - { - ImmutableArray nextVariables = CreateNextVariables(); - SetParentOperation(nextVariables, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyNextVariablesInterlocked, nextVariables, default); - } - - return _lazyNextVariablesInterlocked; - } - } - } - - /// - /// Represents an increment expression. - /// - internal abstract partial class BaseIncrementOrDecrementOperation : Operation, IIncrementOrDecrementOperation - { - public BaseIncrementOrDecrementOperation(bool isDecrement, bool isPostfix, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(isDecrement ? OperationKind.Decrement : OperationKind.Increment, semanticModel, syntax, type, constantValue, isImplicit) - { - IsPostfix = isPostfix; - IsLifted = isLifted; - IsChecked = isChecked; - OperatorMethod = operatorMethod; - } - /// - /// if this is a postfix expression. - /// if this is a prefix expression. - /// - public bool IsPostfix { get; } - /// - /// if this is a 'lifted' increment operator. When there is an - /// operator that is defined to work on a value type, 'lifted' operators are - /// created to work on the versions of those - /// value types. - /// - public bool IsLifted { get; } - /// - /// if overflow checking is performed for the arithmetic operation. - /// - public bool IsChecked { get; } - /// - /// Operator method used by the operation, null if the operation does not use an operator method. - /// - public IMethodSymbol OperatorMethod { get; } - public override IEnumerable Children - { - get - { - if (Target != null) - { - yield return Target; - } - } - } - /// - /// Target of the assignment. - /// - public abstract IOperation Target { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitIncrementOrDecrement(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitIncrementOrDecrement(this, argument); - } - } - - /// - /// Represents an increment expression. - /// - internal sealed partial class IncrementOrDecrementOperation : BaseIncrementOrDecrementOperation, IIncrementOrDecrementOperation - { - public IncrementOrDecrementOperation(bool isDecrement, bool isPostfix, bool isLifted, bool isChecked, IOperation target, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(isDecrement, isPostfix, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) - { - Target = SetParentOperation(target, this); - } - - public override IOperation Target { get; } - } - - /// - /// Represents an increment expression. - /// - internal abstract class LazyIncrementOrDecrementOperation : BaseIncrementOrDecrementOperation, IIncrementOrDecrementOperation - { - private IOperation _lazyTargetInterlocked = s_unset; - - public LazyIncrementOrDecrementOperation(bool isDecrement, bool isPostfix, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(isDecrement, isPostfix, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateTarget(); - - public override IOperation Target - { - get - { - if (_lazyTargetInterlocked == s_unset) - { - IOperation target = CreateTarget(); - SetParentOperation(target, this); - Interlocked.CompareExchange(ref _lazyTargetInterlocked, target, s_unset); - } - - return _lazyTargetInterlocked; - } - } - } - - /// - /// Represents an interpolated string expression. - /// - internal abstract partial class BaseInterpolatedStringOperation : Operation, IInterpolatedStringOperation - { - protected BaseInterpolatedStringOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.InterpolatedString, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - foreach (var part in Parts) - { - if (part != null) - { - yield return part; - } - } - } - } - /// - /// Constituent parts of interpolated string, each of which is an . - /// - public abstract ImmutableArray Parts { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitInterpolatedString(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitInterpolatedString(this, argument); - } - } - - /// - /// Represents an interpolated string expression. - /// - internal sealed partial class InterpolatedStringOperation : BaseInterpolatedStringOperation, IInterpolatedStringOperation - { - public InterpolatedStringOperation(ImmutableArray parts, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Parts = SetParentOperation(parts, this); - } - - public override ImmutableArray Parts { get; } - } - - /// - /// Represents an interpolated string expression. - /// - internal abstract class LazyInterpolatedStringOperation : BaseInterpolatedStringOperation, IInterpolatedStringOperation - { - private ImmutableArray _lazyPartsInterlocked; - - public LazyInterpolatedStringOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateParts(); - - public override ImmutableArray Parts - { - get - { - if (_lazyPartsInterlocked.IsDefault) - { - ImmutableArray parts = CreateParts(); - SetParentOperation(parts, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyPartsInterlocked, parts, default); - } - - return _lazyPartsInterlocked; - } - } - } - - /// - /// Represents a constituent string literal part of an interpolated string expression. - /// - internal abstract partial class BaseInterpolatedStringTextOperation : Operation, IInterpolatedStringTextOperation - { - protected BaseInterpolatedStringTextOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.InterpolatedStringText, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Text != null) - { - yield return Text; - } - } - } - /// - /// Text content. - /// - public abstract IOperation Text { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitInterpolatedStringText(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitInterpolatedStringText(this, argument); - } - } - - /// - /// Represents a constituent string literal part of an interpolated string expression. - /// - internal sealed partial class InterpolatedStringTextOperation : BaseInterpolatedStringTextOperation, IInterpolatedStringTextOperation - { - public InterpolatedStringTextOperation(IOperation text, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Text = SetParentOperation(text, this); - } - - public override IOperation Text { get; } - } - - /// - /// Represents a constituent string literal part of an interpolated string expression. - /// - internal abstract class LazyInterpolatedStringTextOperation : BaseInterpolatedStringTextOperation, IInterpolatedStringTextOperation - { - private IOperation _lazyTextInterlocked = s_unset; - - public LazyInterpolatedStringTextOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateText(); - - public override IOperation Text - { - get - { - if (_lazyTextInterlocked == s_unset) - { - IOperation text = CreateText(); - SetParentOperation(text, this); - Interlocked.CompareExchange(ref _lazyTextInterlocked, text, s_unset); - } - - return _lazyTextInterlocked; - } - } - } - - /// - /// Represents a constituent interpolation part of an interpolated string expression. - /// - internal abstract partial class BaseInterpolationOperation : Operation, IInterpolationOperation - { - protected BaseInterpolationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Interpolation, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Expression != null) - { - yield return Expression; - } - if (Alignment != null) - { - yield return Alignment; - } - if (FormatString != null) - { - yield return FormatString; - } - } - } - /// - /// Expression of the interpolation. - /// - public abstract IOperation Expression { get; } - /// - /// Optional alignment of the interpolation. - /// - public abstract IOperation Alignment { get; } - /// - /// Optional format string of the interpolation. - /// - public abstract IOperation FormatString { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitInterpolation(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitInterpolation(this, argument); - } - } - - /// - /// Represents a constituent interpolation part of an interpolated string expression. - /// - internal sealed partial class InterpolationOperation : BaseInterpolationOperation, IInterpolationOperation - { - public InterpolationOperation(IOperation expression, IOperation alignment, IOperation formatString, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Expression = SetParentOperation(expression, this); - Alignment = SetParentOperation(alignment, this); - FormatString = SetParentOperation(formatString, this); - } - - public override IOperation Expression { get; } - public override IOperation Alignment { get; } - public override IOperation FormatString { get; } - } - - /// - /// Represents a constituent interpolation part of an interpolated string expression. - /// - internal abstract class LazyInterpolationOperation : BaseInterpolationOperation, IInterpolationOperation - { - private IOperation _lazyExpressionInterlocked = s_unset; - private IOperation _lazyAlignmentInterlocked = s_unset; - private IOperation _lazyFormatStringInterlocked = s_unset; - - public LazyInterpolationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateExpression(); - protected abstract IOperation CreateAlignment(); - protected abstract IOperation CreateFormatString(); - - public override IOperation Expression - { - get - { - if (_lazyExpressionInterlocked == s_unset) - { - IOperation expression = CreateExpression(); - SetParentOperation(expression, this); - Interlocked.CompareExchange(ref _lazyExpressionInterlocked, expression, s_unset); - } - - return _lazyExpressionInterlocked; - } - } - - public override IOperation Alignment - { - get - { - if (_lazyAlignmentInterlocked == s_unset) - { - IOperation alignment = CreateAlignment(); - SetParentOperation(alignment, this); - Interlocked.CompareExchange(ref _lazyAlignmentInterlocked, alignment, s_unset); - } - - return _lazyAlignmentInterlocked; - } - } - - public override IOperation FormatString - { - get - { - if (_lazyFormatStringInterlocked == s_unset) - { - IOperation formatString = CreateFormatString(); - SetParentOperation(formatString, this); - Interlocked.CompareExchange(ref _lazyFormatStringInterlocked, formatString, s_unset); - } - - return _lazyFormatStringInterlocked; - } - } - } - - /// - /// This interface is reserved for implementation by its associated APIs. We reserve the right to - /// change it in the future. - /// - internal abstract partial class BaseInvalidOperation : Operation, IInvalidOperation - { - protected BaseInvalidOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Invalid, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitInvalid(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitInvalid(this, argument); - } - } - - /// - /// This interface is reserved for implementation by its associated APIs. We reserve the right to - /// change it in the future. - /// - internal sealed partial class InvalidOperation : BaseInvalidOperation, IInvalidOperation - { - public InvalidOperation(ImmutableArray children, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - // we don't allow null children. - Debug.Assert(children.All(o => o != null)); - Children = SetParentOperation(children, this); - } - public override IEnumerable Children { get; } - } - - /// - /// This interface is reserved for implementation by its associated APIs. We reserve the right to - /// change it in the future. - /// - internal abstract class LazyInvalidOperation : BaseInvalidOperation, IInvalidOperation - { - private ImmutableArray _lazyChildrenInterlocked; - - public LazyInvalidOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateChildren(); - - public override IEnumerable Children - { - get - { - if (_lazyChildrenInterlocked.IsDefault) - { - ImmutableArray children = CreateChildren(); - SetParentOperation(children, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyChildrenInterlocked, children, default); - } - - return _lazyChildrenInterlocked; - } - } - } - - /// - /// Represents a C# or VB method invocation. - /// - internal abstract partial class BaseInvocationOperation : Operation, IInvocationOperation - { - protected BaseInvocationOperation(IMethodSymbol targetMethod, bool isVirtual, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Invocation, semanticModel, syntax, type, constantValue, isImplicit) - { - TargetMethod = targetMethod; - IsVirtual = isVirtual; - } - /// - /// Method to be invoked. - /// - public IMethodSymbol TargetMethod { get; } - /// - /// True if the invocation uses a virtual mechanism, and false otherwise. - /// - public bool IsVirtual { get; } - public override IEnumerable Children - { - get - { - if (Instance != null) - { - yield return Instance; - } - foreach (var argument in Arguments) - { - if (argument != null) - { - yield return argument; - } - } - } - } - /// - /// 'This' or 'Me' instance to be supplied to the method, or null if the method is static. - /// - public abstract IOperation Instance { get; } - /// - /// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order. - /// - /// - /// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays. - /// Default values are supplied for optional arguments missing in source. - /// - public abstract ImmutableArray Arguments { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitInvocation(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitInvocation(this, argument); - } - } - - /// - /// Represents a C# or VB method invocation. - /// - internal sealed partial class InvocationOperation : BaseInvocationOperation, IInvocationOperation - { - public InvocationOperation(IMethodSymbol targetMethod, IOperation instance, bool isVirtual, ImmutableArray arguments, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(targetMethod, isVirtual, semanticModel, syntax, type, constantValue, isImplicit) - { - Instance = SetParentOperation(instance, this); - Arguments = SetParentOperation(arguments, this); - } - - public override IOperation Instance { get; } - public override ImmutableArray Arguments { get; } - } - - /// - /// Represents a C# or VB method invocation. - /// - internal abstract class LazyInvocationOperation : BaseInvocationOperation, IInvocationOperation - { - private IOperation _lazyInstanceInterlocked = s_unset; - private ImmutableArray _lazyArgumentsInterlocked; - - public LazyInvocationOperation(IMethodSymbol targetMethod, bool isVirtual, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(targetMethod, isVirtual, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateInstance(); - protected abstract ImmutableArray CreateArguments(); - - public override IOperation Instance - { - get - { - if (_lazyInstanceInterlocked == s_unset) - { - IOperation instance = CreateInstance(); - SetParentOperation(instance, this); - Interlocked.CompareExchange(ref _lazyInstanceInterlocked, instance, s_unset); - } - - return _lazyInstanceInterlocked; - } - } - - public override ImmutableArray Arguments - { - get - { - if (_lazyArgumentsInterlocked.IsDefault) - { - ImmutableArray arguments = CreateArguments(); - SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); - } - - return _lazyArgumentsInterlocked; - } - } - } - - /// - /// Represents a VB raise event statement. - /// - internal abstract partial class BaseRaiseEventOperation : Operation, IRaiseEventOperation - { - protected BaseRaiseEventOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.RaiseEvent, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (EventReference != null) - { - yield return EventReference; - } - foreach (var argument in Arguments) - { - if (argument != null) - { - yield return argument; - } - } - } - } - /// - /// Reference to the event to be raised. - /// - public abstract IEventReferenceOperation EventReference { get; } - public abstract ImmutableArray Arguments { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitRaiseEvent(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitRaiseEvent(this, argument); - } - } - - /// - /// Represents a VB raise event statement. - /// - internal sealed partial class RaiseEventOperation : BaseRaiseEventOperation, IRaiseEventOperation - { - public RaiseEventOperation(IEventReferenceOperation eventReference, ImmutableArray arguments, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - EventReference = SetParentOperation(eventReference, this); - Arguments = SetParentOperation(arguments, this); - } - - public override IEventReferenceOperation EventReference { get; } - public override ImmutableArray Arguments { get; } - } - - /// - /// Represents a VB raise event statement. - /// - internal abstract class LazyRaiseEventOperation : BaseRaiseEventOperation, IRaiseEventOperation - { - private IEventReferenceOperation _lazyEventReferenceInterlocked = s_unsetEventReference; - private ImmutableArray _lazyArgumentsInterlocked; - - public LazyRaiseEventOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IEventReferenceOperation CreateEventReference(); - protected abstract ImmutableArray CreateArguments(); - - public override IEventReferenceOperation EventReference - { - get - { - if (_lazyEventReferenceInterlocked == s_unsetEventReference) - { - IEventReferenceOperation eventReference = CreateEventReference(); - SetParentOperation(eventReference, this); - Interlocked.CompareExchange(ref _lazyEventReferenceInterlocked, eventReference, s_unsetEventReference); - } - - return _lazyEventReferenceInterlocked; - } - } - - public override ImmutableArray Arguments - { - get - { - if (_lazyArgumentsInterlocked.IsDefault) - { - ImmutableArray arguments = CreateArguments(); - SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); - } - - return _lazyArgumentsInterlocked; - } - } - } - - /// - /// Represents an expression that tests if a value is of a specific type. - /// - internal abstract partial class BaseIsTypeOperation : Operation, IIsTypeOperation - { - protected BaseIsTypeOperation(ITypeSymbol typeOperand, bool isNegated, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.IsType, semanticModel, syntax, type, constantValue, isImplicit) - { - TypeOperand = typeOperand; - IsNegated = isNegated; - } - /// - /// Type for which to test. - /// - public ITypeSymbol TypeOperand { get; } - /// - /// Flag indicating if this is an "is not" type expression. - /// True for VB "TypeOf ... IsNot ..." expression. - /// False, otherwise. - /// - public bool IsNegated { get; } - public override IEnumerable Children - { - get - { - if (ValueOperand != null) - { - yield return ValueOperand; - } - } - } - /// - /// Value to test. - /// - public abstract IOperation ValueOperand { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitIsType(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitIsType(this, argument); - } - } - - /// - /// Represents an expression that tests if a value is of a specific type. - /// - internal sealed partial class IsTypeOperation : BaseIsTypeOperation, IIsTypeOperation - { - public IsTypeOperation(IOperation valueOperand, ITypeSymbol typeOperand, bool isNegated, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(typeOperand, isNegated, semanticModel, syntax, type, constantValue, isImplicit) - { - ValueOperand = SetParentOperation(valueOperand, this); - } - - public override IOperation ValueOperand { get; } - } - - /// - /// Represents an expression that tests if a value is of a specific type. - /// - internal abstract class LazyIsTypeOperation : BaseIsTypeOperation, IIsTypeOperation - { - private IOperation _lazyOperandInterlocked = s_unset; - - public LazyIsTypeOperation(ITypeSymbol isType, bool isNotTypeExpression, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(isType, isNotTypeExpression, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValueOperand(); - - public override IOperation ValueOperand - { - get - { - if (_lazyOperandInterlocked == s_unset) - { - IOperation valueOperand = CreateValueOperand(); - SetParentOperation(valueOperand, this); - Interlocked.CompareExchange(ref _lazyOperandInterlocked, valueOperand, s_unset); - } - - return _lazyOperandInterlocked; - } - } - } - - /// - /// Represents a C# or VB label statement. - /// - internal abstract partial class BaseLabeledOperation : Operation, ILabeledOperation - { - protected BaseLabeledOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Labeled, semanticModel, syntax, type, constantValue, isImplicit) - { - Label = label; - } - /// - /// Label that can be the target of branches. - /// - public ILabelSymbol Label { get; } - public override IEnumerable Children - { - get - { - if (Operation != null) - { - yield return Operation; - } - } - } - /// - /// Statement that has been labeled. - /// - public abstract IOperation Operation { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitLabeled(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitLabeled(this, argument); - } - } - - /// - /// Represents a C# or VB label statement. - /// - internal sealed partial class LabeledOperation : BaseLabeledOperation, ILabeledOperation - { - public LabeledOperation(ILabelSymbol label, IOperation operation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(label, semanticModel, syntax, type, constantValue, isImplicit) - { - Operation = SetParentOperation(operation, this); - } - - public override IOperation Operation { get; } - } - - /// - /// Represents a C# or VB label statement. - /// - internal abstract class LazyLabeledOperation : BaseLabeledOperation, ILabeledOperation - { - private IOperation _lazyOperationInterlocked = s_unset; - - public LazyLabeledOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(label, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperation(); - - public override IOperation Operation - { - get - { - if (_lazyOperationInterlocked == s_unset) - { - IOperation operation = CreateOperation(); - SetParentOperation(operation, this); - Interlocked.CompareExchange(ref _lazyOperationInterlocked, operation, s_unset); - } - - return _lazyOperationInterlocked; - } - } - } - - internal abstract partial class BaseAnonymousFunctionOperation : Operation, IAnonymousFunctionOperation - { - protected BaseAnonymousFunctionOperation(IMethodSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.AnonymousFunction, semanticModel, syntax, type, constantValue, isImplicit) - { - Symbol = symbol; - } - public IMethodSymbol Symbol { get; } - public override IEnumerable Children - { - get - { - if (Body != null) - { - yield return Body; - } - } - } - public abstract IBlockOperation Body { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitAnonymousFunction(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitAnonymousFunction(this, argument); - } - } - - internal sealed partial class AnonymousFunctionOperation : BaseAnonymousFunctionOperation, IAnonymousFunctionOperation - { - public AnonymousFunctionOperation(IMethodSymbol symbol, IBlockOperation body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(symbol, semanticModel, syntax, type, constantValue, isImplicit) - { - Body = SetParentOperation(body, this); - } - - public override IBlockOperation Body { get; } - } - - internal abstract class LazyAnonymousFunctionOperation : BaseAnonymousFunctionOperation, IAnonymousFunctionOperation - { - private IBlockOperation _lazyBodyInterlocked = s_unsetBlock; - - public LazyAnonymousFunctionOperation(IMethodSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(symbol, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IBlockOperation CreateBody(); - - public override IBlockOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unsetBlock) - { - IBlockOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unsetBlock); - } - - return _lazyBodyInterlocked; - } - } - } - - internal sealed class FlowAnonymousFunctionOperation : Operation, IFlowAnonymousFunctionOperation - { - public readonly ControlFlowGraphBuilder.Context Context; - public readonly IAnonymousFunctionOperation Original; - - public FlowAnonymousFunctionOperation(in ControlFlowGraphBuilder.Context context, IAnonymousFunctionOperation original, bool isImplicit) : - base(OperationKind.FlowAnonymousFunction, semanticModel: null, original.Syntax, original.Type, original.ConstantValue, isImplicit) - { - Context = context; - Original = original; - } - public IMethodSymbol Symbol => Original.Symbol; - public override IEnumerable Children - { - get - { - return Array.Empty(); - } - } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitFlowAnonymousFunction(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitFlowAnonymousFunction(this, argument); - } - } - - internal abstract partial class BaseDelegateCreationOperation : Operation, IDelegateCreationOperation - { - public BaseDelegateCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.DelegateCreation, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Target != null) - { - yield return Target; - } - } - } - public abstract IOperation Target { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitDelegateCreation(this); - } - - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitDelegateCreation(this, argument); - } - } - - internal sealed partial class DelegateCreationOperation : BaseDelegateCreationOperation - { - public DelegateCreationOperation(IOperation target, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Target = SetParentOperation(target, this); - } - - public override IOperation Target { get; } - } - - internal abstract class LazyDelegateCreationOperation : BaseDelegateCreationOperation - { - private IOperation _lazyTargetInterlocked = s_unset; - - public LazyDelegateCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateTarget(); - - public override IOperation Target - { - get - { - if (_lazyTargetInterlocked == s_unset) - { - IOperation target = CreateTarget(); - SetParentOperation(target, this); - Interlocked.CompareExchange(ref _lazyTargetInterlocked, target, s_unset); - } - - return _lazyTargetInterlocked; - } - } - } - - /// - /// Represents a dynamic access to a member of a class, struct, or module. - /// - internal abstract partial class BaseDynamicMemberReferenceOperation : Operation, IDynamicMemberReferenceOperation - { - protected BaseDynamicMemberReferenceOperation(string memberName, ImmutableArray typeArguments, ITypeSymbol containingType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.DynamicMemberReference, semanticModel, syntax, type, constantValue, isImplicit) - { - MemberName = memberName; - TypeArguments = typeArguments; - ContainingType = containingType; - } - - /// - /// Name of the member. - /// - public string MemberName { get; } - /// - /// Type arguments. - /// - public ImmutableArray TypeArguments { get; } - /// - /// The containing type of this expression. In C#, this will always be null. - /// - public ITypeSymbol ContainingType { get; } - - public override IEnumerable Children - { - get - { - if (Instance != null) - { - yield return Instance; - } - } - } - /// - /// Instance used to bind the member reference. - /// - public abstract IOperation Instance { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitDynamicMemberReference(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitDynamicMemberReference(this, argument); - } - - } - - /// - /// Represents a dynamic access to a member of a class, struct, or module. - /// - internal sealed partial class DynamicMemberReferenceOperation : BaseDynamicMemberReferenceOperation, IDynamicMemberReferenceOperation - { - public DynamicMemberReferenceOperation(IOperation instance, string memberName, ImmutableArray typeArguments, ITypeSymbol containingType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(memberName, typeArguments, containingType, semanticModel, syntax, type, constantValue, isImplicit) - { - Instance = SetParentOperation(instance, this); - } - - public override IOperation Instance { get; } - } - - /// - /// Represents a dynamic access to a member of a class, struct, or module. - /// - internal abstract class LazyDynamicMemberReferenceOperation : BaseDynamicMemberReferenceOperation, IDynamicMemberReferenceOperation - { - private IOperation _lazyInstanceInterlocked = s_unset; - - public LazyDynamicMemberReferenceOperation(string memberName, ImmutableArray typeArguments, ITypeSymbol containingType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(memberName, typeArguments, containingType, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateInstance(); - - public override IOperation Instance - { - get - { - if (_lazyInstanceInterlocked == s_unset) - { - IOperation instance = CreateInstance(); - SetParentOperation(instance, this); - Interlocked.CompareExchange(ref _lazyInstanceInterlocked, instance, s_unset); - } - - return _lazyInstanceInterlocked; - } - } - } - - /// - /// Represents a C# lock or a VB SyncLock statement. - /// - internal abstract partial class BaseLockOperation : Operation, ILockOperation - { - protected BaseLockOperation(ILocalSymbol lockTakenSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Lock, semanticModel, syntax, type, constantValue, isImplicit) - { - LockTakenSymbol = lockTakenSymbol; - } - - public override IEnumerable Children - { - get - { - if (LockedValue != null) - { - yield return LockedValue; - } - if (Body != null) - { - yield return Body; - } - } - } - /// - /// Expression producing a value to be locked. - /// - public abstract IOperation LockedValue { get; } - /// - /// Body of the lock, to be executed while holding the lock. - /// - public abstract IOperation Body { get; } - public ILocalSymbol LockTakenSymbol { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitLock(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitLock(this, argument); - } - } - - /// - /// Represents a C# lock or a VB SyncLock statement. - /// - internal sealed partial class LockOperation : BaseLockOperation, ILockOperation - { - public LockOperation(IOperation lockedValue, IOperation body, ILocalSymbol lockTakenSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(lockTakenSymbol, semanticModel, syntax, type, constantValue, isImplicit) - { - LockedValue = SetParentOperation(lockedValue, this); - Body = SetParentOperation(body, this); - } - - public override IOperation LockedValue { get; } - public override IOperation Body { get; } - } - - /// - /// Represents a C# lock or a VB SyncLock statement. - /// - internal abstract class LazyLockOperation : BaseLockOperation, ILockOperation - { - private IOperation _lazyLockedValueInterlocked = s_unset; - private IOperation _lazyBodyInterlocked = s_unset; - - public LazyLockOperation(ILocalSymbol lockTakenSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(lockTakenSymbol, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateLockedValue(); - protected abstract IOperation CreateBody(); - - public override IOperation LockedValue - { - get - { - if (_lazyLockedValueInterlocked == s_unset) - { - IOperation lockedValue = CreateLockedValue(); - SetParentOperation(lockedValue, this); - Interlocked.CompareExchange(ref _lazyLockedValueInterlocked, lockedValue, s_unset); - } - - return _lazyLockedValueInterlocked; - } - } - - public override IOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unset) - { - IOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unset); - } - - return _lazyBodyInterlocked; - } - } - } - - /// - /// Represents a C# while, for, foreach, or do statement, or a VB While, For, For Each, or Do statement. - /// - internal abstract partial class LoopOperation : Operation, ILoopOperation - { - protected LoopOperation(LoopKind loopKind, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) - { - LoopKind = loopKind; - Locals = locals; - ContinueLabel = continueLabel; - ExitLabel = exitLabel; - } - /// - /// Kind of the loop. - /// - public LoopKind LoopKind { get; } - /// - /// Declarations local to the loop. - /// - public ImmutableArray Locals { get; } - public ILabelSymbol ContinueLabel { get; } - public ILabelSymbol ExitLabel { get; } - /// - /// Body of the loop. - /// - public abstract IOperation Body { get; } - } - - /// - /// Represents a reference to a member of a class, struct, or interface. - /// - internal abstract partial class BaseMemberReferenceOperation : Operation, IMemberReferenceOperation - { - protected BaseMemberReferenceOperation(ISymbol member, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) - { - Member = member; - } - /// - /// Instance of the type. Null if the reference is to a static/shared member. - /// - public abstract IOperation Instance { get; } - - /// - /// Referenced member. - /// - public ISymbol Member { get; } - } - - /// - /// Represents a reference to a method other than as the target of an invocation. - /// - internal abstract partial class BaseMethodReferenceOperation : BaseMemberReferenceOperation, IMethodReferenceOperation - { - public BaseMethodReferenceOperation(IMethodSymbol method, bool isVirtual, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(method, OperationKind.MethodReference, semanticModel, syntax, type, constantValue, isImplicit) - { - IsVirtual = isVirtual; - } - /// - /// Referenced method. - /// - public IMethodSymbol Method => (IMethodSymbol)Member; - - /// - /// Indicates whether the reference uses virtual semantics. - /// - public bool IsVirtual { get; } - - public override IEnumerable Children - { - get - { - if (Instance != null) - { - yield return Instance; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitMethodReference(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitMethodReference(this, argument); - } - } - - /// - /// Represents a reference to a method other than as the target of an invocation. - /// - internal sealed partial class MethodReferenceOperation : BaseMethodReferenceOperation, IMethodReferenceOperation - { - public MethodReferenceOperation(IMethodSymbol method, bool isVirtual, IOperation instance, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(method, isVirtual, semanticModel, syntax, type, constantValue, isImplicit) - { - Instance = SetParentOperation(instance, this); - } - /// - /// Instance of the type. Null if the reference is to a static/shared member. - /// - public override IOperation Instance { get; } - } - - /// - /// Represents a reference to a method other than as the target of an invocation. - /// - internal abstract class LazyMethodReferenceOperation : BaseMethodReferenceOperation, IMethodReferenceOperation - { - private IOperation _lazyInstanceInterlocked = s_unset; - - public LazyMethodReferenceOperation(IMethodSymbol method, bool isVirtual, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(method, isVirtual, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateInstance(); - - public override IOperation Instance - { - get - { - if (_lazyInstanceInterlocked == s_unset) - { - IOperation instance = CreateInstance(); - SetParentOperation(instance, this); - Interlocked.CompareExchange(ref _lazyInstanceInterlocked, instance, s_unset); - } - - return _lazyInstanceInterlocked; - } - } - } - - /// - /// Represents a null-coalescing expression. - /// - internal abstract partial class BaseCoalesceOperation : Operation, ICoalesceOperation - { - protected BaseCoalesceOperation(IConvertibleConversion convertibleValueConversion, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Coalesce, semanticModel, syntax, type, constantValue, isImplicit) - { - ConvertibleValueConversion = convertibleValueConversion; - } - - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - if (WhenNull != null) - { - yield return WhenNull; - } - } - } - /// - /// Value to be unconditionally evaluated. - /// - public abstract IOperation Value { get; } - /// - /// Value to be evaluated if evaluates to null/Nothing. - /// - public abstract IOperation WhenNull { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitCoalesce(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitCoalesce(this, argument); - } - - // https://github.com/dotnet/roslyn/issues/27599 tracks adding extension methods that expose language specific conversion information - internal IConvertibleConversion ConvertibleValueConversion { get; } - public CommonConversion ValueConversion => ConvertibleValueConversion.ToCommonConversion(); - } - - /// - /// Represents a null-coalescing expression. - /// - internal sealed partial class CoalesceOperation : BaseCoalesceOperation, ICoalesceOperation - { - public CoalesceOperation(IOperation value, IOperation whenNull, IConvertibleConversion convertibleValueConversion, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(convertibleValueConversion, semanticModel, syntax, type, constantValue, isImplicit) - { - Value = SetParentOperation(value, this); - WhenNull = SetParentOperation(whenNull, this); - } - - public override IOperation Value { get; } - public override IOperation WhenNull { get; } - } - - /// - /// Represents a null-coalescing expression. - /// - internal abstract class LazyCoalesceOperation : BaseCoalesceOperation, ICoalesceOperation - { - private IOperation _lazyValueInterlocked = s_unset; - private IOperation _lazyWhenNullInterlocked = s_unset; - - public LazyCoalesceOperation(IConvertibleConversion convertibleValueConversion, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(convertibleValueConversion, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - protected abstract IOperation CreateWhenNull(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - - public override IOperation WhenNull - { - get - { - if (_lazyWhenNullInterlocked == s_unset) - { - IOperation whenNull = CreateWhenNull(); - SetParentOperation(whenNull, this); - Interlocked.CompareExchange(ref _lazyWhenNullInterlocked, whenNull, s_unset); - } - - return _lazyWhenNullInterlocked; - } - } - } - - internal abstract partial class BaseCoalesceAssignmentOperation : Operation, ICoalesceAssignmentOperation - { - protected BaseCoalesceAssignmentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.CoalesceAssignment, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public abstract IOperation Target { get; } - public abstract IOperation Value { get; } - public override IEnumerable Children - { - get - { - if (Target != null) - { - yield return Target; - } - if (Value != null) - { - yield return Value; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitCoalesceAssignment(this); - } - - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitCoalesceAssignment(this, argument); - } - } - - internal sealed class CoalesceAssignmentOperation : BaseCoalesceAssignmentOperation - { - public CoalesceAssignmentOperation(IOperation target, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Target = SetParentOperation(target, this); - Value = SetParentOperation(value, this); - } - - public override IOperation Target { get; } - public override IOperation Value { get; } - } - - internal abstract class LazyCoalesceAssignmentOperation : BaseCoalesceAssignmentOperation - { - private IOperation _lazyTargetInterlocked = s_unset; - private IOperation _lazyWhenNullInterlocked = s_unset; - - public LazyCoalesceAssignmentOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateTarget(); - protected abstract IOperation CreateValue(); - - public override IOperation Target - { - get - { - if (_lazyTargetInterlocked == s_unset) - { - IOperation target = CreateTarget(); - SetParentOperation(target, this); - Interlocked.CompareExchange(ref _lazyTargetInterlocked, target, s_unset); - } - - return _lazyTargetInterlocked; - } - } - - public override IOperation Value - { - get - { - if (_lazyWhenNullInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyWhenNullInterlocked, value, s_unset); - } - - return _lazyWhenNullInterlocked; - } - } - } - - /// - /// Represents a new/New expression. - /// - internal abstract partial class BaseObjectCreationOperation : Operation, IObjectCreationOperation - { - protected BaseObjectCreationOperation(IMethodSymbol constructor, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.ObjectCreation, semanticModel, syntax, type, constantValue, isImplicit) - { - Constructor = constructor; - } - /// - /// Constructor to be invoked on the created instance. - /// - public IMethodSymbol Constructor { get; } - public override IEnumerable Children - { - get - { - foreach (var argument in Arguments) - { - if (argument != null) - { - yield return argument; - } - } - if (Initializer != null) - { - yield return Initializer; - } - } - } - /// - /// Object or collection initializer, if any. - /// - public abstract IObjectOrCollectionInitializerOperation Initializer { get; } - /// - /// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order. - /// - /// - /// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays. - /// Default values are supplied for optional arguments missing in source. - /// - public abstract ImmutableArray Arguments { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitObjectCreation(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitObjectCreation(this, argument); - } - } - - /// - /// Represents a new/New expression. - /// - internal sealed partial class ObjectCreationOperation : BaseObjectCreationOperation, IObjectCreationOperation - { - public ObjectCreationOperation(IMethodSymbol constructor, IObjectOrCollectionInitializerOperation initializer, ImmutableArray arguments, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(constructor, semanticModel, syntax, type, constantValue, isImplicit) - { - Initializer = SetParentOperation(initializer, this); - Arguments = SetParentOperation(arguments, this); - } - - public override IObjectOrCollectionInitializerOperation Initializer { get; } - public override ImmutableArray Arguments { get; } - } - - /// - /// Represents a new/New expression. - /// - internal abstract class LazyObjectCreationOperation : BaseObjectCreationOperation, IObjectCreationOperation - { - private IObjectOrCollectionInitializerOperation _lazyInitializerInterlocked = s_unsetObjectOrCollectionInitializer; - private ImmutableArray _lazyArgumentsInterlocked; - - public LazyObjectCreationOperation(IMethodSymbol constructor, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(constructor, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); - protected abstract ImmutableArray CreateArguments(); - - public override IObjectOrCollectionInitializerOperation Initializer - { - get - { - if (_lazyInitializerInterlocked == s_unsetObjectOrCollectionInitializer) - { - IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); - SetParentOperation(initializer, this); - Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unsetObjectOrCollectionInitializer); - } - - return _lazyInitializerInterlocked; - } - } - - public override ImmutableArray Arguments - { - get - { - if (_lazyArgumentsInterlocked.IsDefault) - { - ImmutableArray arguments = CreateArguments(); - SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); - } - - return _lazyArgumentsInterlocked; - } - } - } - - /// - /// Represents a C# or VB new/New anonymous object creation expression. - /// - internal abstract partial class BaseAnonymousObjectCreationOperation : Operation, IAnonymousObjectCreationOperation - { - protected BaseAnonymousObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.AnonymousObjectCreation, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - foreach (var initializer in Initializers) - { - if (initializer != null) - { - yield return initializer; - } - } - } - } - /// - /// Explicitly-specified member initializers. - /// - public abstract ImmutableArray Initializers { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitAnonymousObjectCreation(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitAnonymousObjectCreation(this, argument); - } - } - - /// - /// Represents a C# or VB new/New anonymous object creation expression. - /// - internal sealed partial class AnonymousObjectCreationOperation : BaseAnonymousObjectCreationOperation, IAnonymousObjectCreationOperation - { - public AnonymousObjectCreationOperation(ImmutableArray initializers, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Initializers = SetParentOperation(initializers, this); - } - - public override ImmutableArray Initializers { get; } - } - - /// - /// Represents a C# or VB new/New anonymous object creation expression. - /// - internal abstract class LazyAnonymousObjectCreationOperation : BaseAnonymousObjectCreationOperation, IAnonymousObjectCreationOperation - { - private ImmutableArray _lazyInitializersInterlocked; - - public LazyAnonymousObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateInitializers(); - - public override ImmutableArray Initializers - { - get - { - if (_lazyInitializersInterlocked.IsDefault) - { - ImmutableArray initializers = CreateInitializers(); - SetParentOperation(initializers, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyInitializersInterlocked, initializers, default); - } - - return _lazyInitializersInterlocked; - } - } - } - - /// - /// Represents an initialization of a parameter at the point of declaration. - /// - internal abstract partial class BaseParameterInitializerOperation : SymbolInitializer, IParameterInitializerOperation - { - public BaseParameterInitializerOperation(ImmutableArray locals, IParameterSymbol parameter, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) - { - Locals = locals; - Parameter = parameter; - } - - public ImmutableArray Locals { get; } - - /// - /// Initialized parameter. - /// - public IParameterSymbol Parameter { get; } - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitParameterInitializer(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitParameterInitializer(this, argument); - } - } - - /// - /// Represents an initialization of a parameter at the point of declaration. - /// - internal sealed partial class ParameterInitializerOperation : BaseParameterInitializerOperation, IParameterInitializerOperation - { - public ParameterInitializerOperation(ImmutableArray locals, IParameterSymbol parameter, IOperation value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, parameter, kind, semanticModel, syntax, type, constantValue, isImplicit) - { - Value = SetParentOperation(value, this); - } - public override IOperation Value { get; } - } - - /// - /// Represents an initialization of a parameter at the point of declaration. - /// - internal abstract class LazyParameterInitializerOperation : BaseParameterInitializerOperation, IParameterInitializerOperation - { - private IOperation _lazyValueInterlocked = s_unset; - - public LazyParameterInitializerOperation(ImmutableArray locals, IParameterSymbol parameter, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, parameter, kind, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents a parenthesized expression. - /// - internal abstract partial class BaseParenthesizedOperation : Operation, IParenthesizedOperation - { - protected BaseParenthesizedOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Parenthesized, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Operand != null) - { - yield return Operand; - } - } - } - /// - /// Operand enclosed in parentheses. - /// - public abstract IOperation Operand { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitParenthesized(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitParenthesized(this, argument); - } - } - - /// - /// Represents a parenthesized expression. - /// - internal sealed partial class ParenthesizedOperation : BaseParenthesizedOperation, IParenthesizedOperation - { - public ParenthesizedOperation(IOperation operand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Operand = SetParentOperation(operand, this); - } - - public override IOperation Operand { get; } - } - - /// - /// Represents a parenthesized expression. - /// - internal abstract class LazyParenthesizedOperation : BaseParenthesizedOperation, IParenthesizedOperation - { - private IOperation _lazyOperandInterlocked = s_unset; - - public LazyParenthesizedOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperand(); - - public override IOperation Operand - { - get - { - if (_lazyOperandInterlocked == s_unset) - { - IOperation operand = CreateOperand(); - SetParentOperation(operand, this); - Interlocked.CompareExchange(ref _lazyOperandInterlocked, operand, s_unset); - } - - return _lazyOperandInterlocked; - } - } - } - - /// - /// Represents an initialization of a property. - /// - internal abstract partial class BasePropertyInitializerOperation : SymbolInitializer, IPropertyInitializerOperation - { - public BasePropertyInitializerOperation(ImmutableArray locals, ImmutableArray initializedProperties, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) - { - Locals = locals; - InitializedProperties = initializedProperties; - } - - public ImmutableArray Locals { get; } - - /// - /// Initialized properties. There can be multiple properties for Visual Basic 'WithEvents' declaration with AsNew clause. - /// - public ImmutableArray InitializedProperties { get; } - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitPropertyInitializer(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitPropertyInitializer(this, argument); - } - } - - /// - /// Represents an initialization of a property. - /// - internal sealed partial class PropertyInitializerOperation : BasePropertyInitializerOperation, IPropertyInitializerOperation - { - public PropertyInitializerOperation(ImmutableArray locals, ImmutableArray initializedProperties, IOperation value, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, initializedProperties, kind, semanticModel, syntax, type, constantValue, isImplicit) - { - Value = SetParentOperation(value, this); - } - public override IOperation Value { get; } - } - - /// - /// Represents an initialization of a property. - /// - internal abstract class LazyPropertyInitializerOperation : BasePropertyInitializerOperation, IPropertyInitializerOperation - { - private IOperation _lazyValueInterlocked = s_unset; - - public LazyPropertyInitializerOperation(ImmutableArray locals, ImmutableArray initializedProperties, OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, initializedProperties, kind, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents a reference to a property. - /// - internal abstract partial class BasePropertyReferenceOperation : BaseMemberReferenceOperation, IPropertyReferenceOperation - { - protected BasePropertyReferenceOperation(IPropertySymbol property, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(property, OperationKind.PropertyReference, semanticModel, syntax, type, constantValue, isImplicit) - { - } - /// - /// Referenced property. - /// - public IPropertySymbol Property => (IPropertySymbol)Member; - public override IEnumerable Children - { - get - { - if (Instance != null) - { - yield return Instance; - } - foreach (var argument in Arguments) - { - if (argument != null) - { - yield return argument; - } - } - } - } - /// - /// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order. - /// - /// - /// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays. - /// Default values are supplied for optional arguments missing in source. - /// - public abstract ImmutableArray Arguments { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitPropertyReference(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitPropertyReference(this, argument); - } - } - - /// - /// Represents a reference to a property. - /// - internal sealed partial class PropertyReferenceOperation : BasePropertyReferenceOperation, IPropertyReferenceOperation - { - public PropertyReferenceOperation(IPropertySymbol property, IOperation instance, ImmutableArray arguments, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(property, semanticModel, syntax, type, constantValue, isImplicit) - { - Instance = SetParentOperation(instance, this); - Arguments = SetParentOperation(arguments, this); - } - public override IOperation Instance { get; } - public override ImmutableArray Arguments { get; } - } - - /// - /// Represents a reference to a property. - /// - internal abstract class LazyPropertyReferenceOperation : BasePropertyReferenceOperation, IPropertyReferenceOperation - { - private IOperation _lazyInstanceInterlocked = s_unset; - private ImmutableArray _lazyArgumentsInterlocked; - - public LazyPropertyReferenceOperation(IPropertySymbol property, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(property, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateInstance(); - protected abstract ImmutableArray CreateArguments(); - - public override IOperation Instance - { - get - { - if (_lazyInstanceInterlocked == s_unset) - { - IOperation instance = CreateInstance(); - SetParentOperation(instance, this); - Interlocked.CompareExchange(ref _lazyInstanceInterlocked, instance, s_unset); - } - - return _lazyInstanceInterlocked; - } - } - - public override ImmutableArray Arguments - { - get - { - if (_lazyArgumentsInterlocked.IsDefault) - { - ImmutableArray arguments = CreateArguments(); - SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); - } - - return _lazyArgumentsInterlocked; - } - } - } - - /// - /// Represents Case x To y in VB. - /// - internal abstract partial class BaseRangeCaseClauseOperation : BaseCaseClauseOperation, IRangeCaseClauseOperation - { - public BaseRangeCaseClauseOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(CaseKind.Range, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (MinimumValue != null) - { - yield return MinimumValue; - } - if (MaximumValue != null) - { - yield return MaximumValue; - } - } - } - /// - /// Minimum value of the case range. - /// - public abstract IOperation MinimumValue { get; } - /// - /// Maximum value of the case range. - /// - public abstract IOperation MaximumValue { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitRangeCaseClause(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitRangeCaseClause(this, argument); - } - } - - /// - /// Represents Case x To y in VB. - /// - internal sealed partial class RangeCaseClauseOperation : BaseRangeCaseClauseOperation, IRangeCaseClauseOperation - { - public RangeCaseClauseOperation(IOperation minimumValue, IOperation maximumValue, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - MinimumValue = SetParentOperation(minimumValue, this); - MaximumValue = SetParentOperation(maximumValue, this); - } - - public override IOperation MinimumValue { get; } - public override IOperation MaximumValue { get; } - } - - /// - /// Represents Case x To y in VB. - /// - internal abstract class LazyRangeCaseClauseOperation : BaseRangeCaseClauseOperation, IRangeCaseClauseOperation - { - private IOperation _lazyMinimumValueInterlocked = s_unset; - private IOperation _lazyMaximumValueInterlocked = s_unset; - - public LazyRangeCaseClauseOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateMinimumValue(); - protected abstract IOperation CreateMaximumValue(); - - public override IOperation MinimumValue - { - get - { - if (_lazyMinimumValueInterlocked == s_unset) - { - IOperation minimumValue = CreateMinimumValue(); - SetParentOperation(minimumValue, this); - Interlocked.CompareExchange(ref _lazyMinimumValueInterlocked, minimumValue, s_unset); - } - - return _lazyMinimumValueInterlocked; - } - } - - public override IOperation MaximumValue - { - get - { - if (_lazyMaximumValueInterlocked == s_unset) - { - IOperation maximumValue = CreateMaximumValue(); - SetParentOperation(maximumValue, this); - Interlocked.CompareExchange(ref _lazyMaximumValueInterlocked, maximumValue, s_unset); - } - - return _lazyMaximumValueInterlocked; - } - } - } - - /// - /// Represents Case Is op x in VB. - /// - internal abstract partial class BaseRelationalCaseClauseOperation : BaseCaseClauseOperation, IRelationalCaseClauseOperation - { - public BaseRelationalCaseClauseOperation(BinaryOperatorKind relation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(CaseKind.Relational, semanticModel, syntax, type, constantValue, isImplicit) - { - Relation = relation; - } - - /// - /// Relational operator used to compare the switch value with the case value. - /// - public BinaryOperatorKind Relation { get; } - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - } - } - /// - /// Case value. - /// - public abstract IOperation Value { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitRelationalCaseClause(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitRelationalCaseClause(this, argument); - } - } - - /// - /// Represents Case Is op x in VB. - /// - internal sealed partial class RelationalCaseClauseOperation : BaseRelationalCaseClauseOperation, IRelationalCaseClauseOperation - { - public RelationalCaseClauseOperation(IOperation value, BinaryOperatorKind relation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(relation, semanticModel, syntax, type, constantValue, isImplicit) - { - Value = SetParentOperation(value, this); - } - - public override IOperation Value { get; } - } - - /// - /// Represents Case Is op x in VB. - /// - internal abstract class LazyRelationalCaseClauseOperation : BaseRelationalCaseClauseOperation, IRelationalCaseClauseOperation - { - private IOperation _lazyValueInterlocked = s_unset; - - public LazyRelationalCaseClauseOperation(BinaryOperatorKind relation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(relation, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents a C# return or a VB Return statement. - /// - internal abstract partial class BaseReturnOperation : Operation, IReturnOperation - { - protected BaseReturnOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) - { - Debug.Assert(kind == OperationKind.Return - || kind == OperationKind.YieldReturn - || kind == OperationKind.YieldBreak); - } - - public override IEnumerable Children - { - get - { - if (ReturnedValue != null) - { - yield return ReturnedValue; - } - } - } - /// - /// Value to be returned. - /// - public abstract IOperation ReturnedValue { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitReturn(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitReturn(this, argument); - } - } - - /// - /// Represents a C# return or a VB Return statement. - /// - internal sealed partial class ReturnOperation : BaseReturnOperation, IReturnOperation - { - public ReturnOperation(OperationKind kind, IOperation returnedValue, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) - { - ReturnedValue = SetParentOperation(returnedValue, this); - } - - public override IOperation ReturnedValue { get; } - } - - /// - /// Represents a C# return or a VB Return statement. - /// - internal abstract class LazyReturnOperation : BaseReturnOperation, IReturnOperation - { - private IOperation _lazyReturnedValueInterlocked = s_unset; - - public LazyReturnOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateReturnedValue(); - - public override IOperation ReturnedValue - { - get - { - if (_lazyReturnedValueInterlocked == s_unset) - { - IOperation returnedValue = CreateReturnedValue(); - SetParentOperation(returnedValue, this); - Interlocked.CompareExchange(ref _lazyReturnedValueInterlocked, returnedValue, s_unset); - } - - return _lazyReturnedValueInterlocked; - } - } - } - - /// - /// Represents case x in C# or Case x in VB. - /// - internal abstract partial class BaseSingleValueCaseClauseOperation : BaseCaseClauseOperation, ISingleValueCaseClauseOperation - { - public BaseSingleValueCaseClauseOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(CaseKind.SingleValue, label, OperationKind.CaseClause, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - } - } - /// - /// Case value. - /// - public abstract IOperation Value { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitSingleValueCaseClause(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitSingleValueCaseClause(this, argument); - } - } - - /// - /// Represents case x in C# or Case x in VB. - /// - internal sealed partial class SingleValueCaseClauseOperation : BaseSingleValueCaseClauseOperation, ISingleValueCaseClauseOperation - { - public SingleValueCaseClauseOperation(ILabelSymbol label, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(label, semanticModel, syntax, type, constantValue, isImplicit) - { - Value = SetParentOperation(value, this); - } - - public override IOperation Value { get; } - } - - /// - /// Represents case x in C# or Case x in VB. - /// - internal abstract class LazySingleValueCaseClauseOperation : BaseSingleValueCaseClauseOperation, ISingleValueCaseClauseOperation - { - private IOperation _lazyValueInterlocked = s_unset; - - public LazySingleValueCaseClauseOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(label, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - internal sealed partial class DefaultCaseClauseOperation : BaseCaseClauseOperation - { - public DefaultCaseClauseOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - this(CaseKind.Default, label, semanticModel, syntax, type, constantValue, isImplicit) - { - } - } - - /// - /// Represents a C# case or VB Case statement. - /// - internal abstract partial class BaseSwitchCaseOperation : Operation, ISwitchCaseOperation - { - protected BaseSwitchCaseOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.SwitchCase, semanticModel, syntax, type, constantValue, isImplicit) - { - Locals = locals; - } - - public ImmutableArray Locals { get; } - - public override IEnumerable Children - { - get - { - foreach (var clause in Clauses) - { - if (clause != null) - { - yield return clause; - } - } - foreach (var body in Body) - { - if (body != null) - { - yield return body; - } - } - } - } - /// - /// Clauses of the case. For C# there is one clause per case, but for VB there can be multiple. - /// - public abstract ImmutableArray Clauses { get; } - /// - /// Statements of the case. - /// - public abstract ImmutableArray Body { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitSwitchCase(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitSwitchCase(this, argument); - } - - /// - /// Optional combined logical condition that accounts for all . - /// An instance of with kind - /// is used to refer to the in context of this expression. - /// It is not part of list and likely contains duplicate nodes for - /// nodes exposed by , like , - /// etc. - /// Never set for C# at the moment. - /// - public abstract IOperation Condition { get; } - } - - /// - /// Represents a C# case or VB Case statement. - /// - internal sealed partial class SwitchCaseOperation : BaseSwitchCaseOperation, ISwitchCaseOperation - { - public SwitchCaseOperation(ImmutableArray locals, IOperation condition, ImmutableArray clauses, ImmutableArray body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, semanticModel, syntax, type, constantValue, isImplicit) - { - Clauses = SetParentOperation(clauses, this); - Condition = SetParentOperation(condition, null); - Body = SetParentOperation(body, this); - } - - public override ImmutableArray Clauses { get; } - public override IOperation Condition { get; } - public override ImmutableArray Body { get; } - } - - /// - /// Represents a C# case or VB Case statement. - /// - internal abstract class LazySwitchCaseOperation : BaseSwitchCaseOperation, ISwitchCaseOperation - { - private ImmutableArray _lazyClausesInterlocked; - private IOperation _lazyConditionInterlocked = s_unset; - private ImmutableArray _lazyBodyInterlocked; - - public LazySwitchCaseOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateClauses(); - protected abstract IOperation CreateCondition(); - protected abstract ImmutableArray CreateBody(); - - public override ImmutableArray Clauses - { - get - { - if (_lazyClausesInterlocked.IsDefault) - { - ImmutableArray clauses = CreateClauses(); - SetParentOperation(clauses, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyClausesInterlocked, clauses, default); - } - - return _lazyClausesInterlocked; - } - } - - public override IOperation Condition - { - get - { - if (_lazyConditionInterlocked == s_unset) - { - IOperation condition = CreateCondition(); - SetParentOperation(condition, null); - Interlocked.CompareExchange(ref _lazyConditionInterlocked, condition, s_unset); - } - - return _lazyConditionInterlocked; - } - } - - public override ImmutableArray Body - { - get - { - if (_lazyBodyInterlocked.IsDefault) - { - ImmutableArray body = CreateBody(); - SetParentOperation(body, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyBodyInterlocked, body, default); - } - - return _lazyBodyInterlocked; - } - } - } - - /// - /// Represents a C# switch or VB Select Case statement. - /// - internal abstract partial class BaseSwitchOperation : Operation, ISwitchOperation - { - protected BaseSwitchOperation(ImmutableArray locals, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Switch, semanticModel, syntax, type, constantValue, isImplicit) - { - Locals = locals; - ExitLabel = exitLabel; - } - - public ImmutableArray Locals { get; } - - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - foreach (var @case in Cases) - { - if (@case != null) - { - yield return @case; - } - } - } - } - public ILabelSymbol ExitLabel { get; } - /// - /// Value to be switched upon. - /// - public abstract IOperation Value { get; } - /// - /// Cases of the switch. - /// - public abstract ImmutableArray Cases { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitSwitch(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitSwitch(this, argument); - } - } - - /// - /// Represents a C# switch or VB Select Case statement. - /// - internal sealed partial class SwitchOperation : BaseSwitchOperation, ISwitchOperation - { - public SwitchOperation(ImmutableArray locals, IOperation value, ImmutableArray cases, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - Value = SetParentOperation(value, this); - Cases = SetParentOperation(cases, this); - } - - public override IOperation Value { get; } - public override ImmutableArray Cases { get; } - } - - /// - /// Represents a C# switch or VB Select Case statement. - /// - internal abstract class LazySwitchOperation : BaseSwitchOperation, ISwitchOperation - { - private IOperation _lazyValueInterlocked = s_unset; - private ImmutableArray _lazyCasesInterlocked; - - public LazySwitchOperation(ImmutableArray locals, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - protected abstract ImmutableArray CreateCases(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - - public override ImmutableArray Cases - { - get - { - if (_lazyCasesInterlocked.IsDefault) - { - ImmutableArray cases = CreateCases(); - SetParentOperation(cases, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyCasesInterlocked, cases, default); - } - - return _lazyCasesInterlocked; - } - } - } - - /// - /// Represents an initializer for a field, property, or parameter. - /// - internal abstract partial class SymbolInitializer : Operation - { - protected SymbolInitializer(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(kind, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public abstract IOperation Value { get; } - } - - /// - /// Represents a C# try or a VB Try statement. - /// - internal abstract partial class BaseTryOperation : Operation, ITryOperation - { - protected BaseTryOperation(ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Try, semanticModel, syntax, type, constantValue, isImplicit) - { - ExitLabel = exitLabel; - } - - public override IEnumerable Children - { - get - { - if (Body != null) - { - yield return Body; - } - foreach (var @catch in Catches) - { - if (@catch != null) - { - yield return @catch; - } - } - if (Finally != null) - { - yield return Finally; - } - } - } - public ILabelSymbol ExitLabel { get; } - /// - /// Body of the try, over which the handlers are active. - /// - public abstract IBlockOperation Body { get; } - /// - /// Catch clauses of the try. - /// - public abstract ImmutableArray Catches { get; } - /// - /// Finally handler of the try. - /// - public abstract IBlockOperation Finally { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitTry(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitTry(this, argument); - } - } - - /// - /// Represents a C# try or a VB Try statement. - /// - internal sealed partial class TryOperation : BaseTryOperation, ITryOperation - { - public TryOperation(IBlockOperation body, ImmutableArray catches, IBlockOperation finallyHandler, ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - Body = SetParentOperation(body, this); - Catches = SetParentOperation(catches, this); - Finally = SetParentOperation(finallyHandler, this); - } - - public override IBlockOperation Body { get; } - public override ImmutableArray Catches { get; } - public override IBlockOperation Finally { get; } - } - - /// - /// Represents a C# try or a VB Try statement. - /// - internal abstract class LazyTryOperation : BaseTryOperation, ITryOperation - { - private IBlockOperation _lazyBodyInterlocked = s_unsetBlock; - private ImmutableArray _lazyCatchesInterlocked; - private IBlockOperation _lazyFinallyHandlerInterlocked = s_unsetBlock; - - public LazyTryOperation(ILabelSymbol exitLabel, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(exitLabel, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IBlockOperation CreateBody(); - protected abstract ImmutableArray CreateCatches(); - protected abstract IBlockOperation CreateFinally(); - - public override IBlockOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unsetBlock) - { - IBlockOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unsetBlock); - } - - return _lazyBodyInterlocked; - } - } - - public override ImmutableArray Catches - { - get - { - if (_lazyCatchesInterlocked.IsDefault) - { - ImmutableArray catches = CreateCatches(); - SetParentOperation(catches, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyCatchesInterlocked, catches, default); - } - - return _lazyCatchesInterlocked; - } - } - - public override IBlockOperation Finally - { - get - { - if (_lazyFinallyHandlerInterlocked == s_unsetBlock) - { - IBlockOperation @finally = CreateFinally(); - SetParentOperation(@finally, this); - Interlocked.CompareExchange(ref _lazyFinallyHandlerInterlocked, @finally, s_unsetBlock); - } - - return _lazyFinallyHandlerInterlocked; - } - } - } - - /// - /// Represents a tuple expression. - /// - internal abstract partial class BaseTupleOperation : Operation, ITupleOperation - { - protected BaseTupleOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, ITypeSymbol naturalType, Optional constantValue, bool isImplicit) : - base(OperationKind.Tuple, semanticModel, syntax, type, constantValue, isImplicit) - { - NaturalType = naturalType; - } - - /// - /// Natural type of the tuple, or null if tuple doesn't have a natural type. - /// Natural type can be different from depending on the - /// conversion context, in which the tuple is used. - /// - public ITypeSymbol NaturalType { get; } - - public override IEnumerable Children - { - get - { - foreach (var element in Elements) - { - if (element != null) - { - yield return element; - } - } - } - } - /// - /// Elements for tuple expression. - /// - public abstract ImmutableArray Elements { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitTuple(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitTuple(this, argument); - } - } - - /// - /// Represents a tuple expression. - /// - internal sealed partial class TupleOperation : BaseTupleOperation, ITupleOperation - { - public TupleOperation(ImmutableArray elements, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, ITypeSymbol naturalType, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, naturalType, constantValue, isImplicit) - { - Elements = SetParentOperation(elements, this); - } - - public override ImmutableArray Elements { get; } - } - - /// - /// Represents a tuple expression. - /// - internal abstract class LazyTupleOperation : BaseTupleOperation, ITupleOperation - { - private ImmutableArray _lazyElementsInterlocked; - - public LazyTupleOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, ITypeSymbol naturalType, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, naturalType, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateElements(); - - public override ImmutableArray Elements - { - get - { - if (_lazyElementsInterlocked.IsDefault) - { - ImmutableArray elements = CreateElements(); - SetParentOperation(elements, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyElementsInterlocked, elements, default); - } - - return _lazyElementsInterlocked; - } - } - } - - /// - /// Represents a type parameter object creation expression, i.e. new T(), where T is a type parameter with new constraint. - /// - internal abstract partial class BaseTypeParameterObjectCreationOperation : Operation, ITypeParameterObjectCreationOperation - { - public BaseTypeParameterObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.TypeParameterObjectCreation, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override IEnumerable Children - { - get - { - if (Initializer != null) - { - yield return Initializer; - } - } - } - /// - /// Object or collection initializer, if any. - /// - public abstract IObjectOrCollectionInitializerOperation Initializer { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitTypeParameterObjectCreation(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitTypeParameterObjectCreation(this, argument); - } - } - - /// - /// Represents a type parameter object creation expression, i.e. new T(), where T is a type parameter with new constraint. - /// - internal sealed partial class TypeParameterObjectCreationOperation : BaseTypeParameterObjectCreationOperation, ITypeParameterObjectCreationOperation - { - public TypeParameterObjectCreationOperation(IObjectOrCollectionInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Initializer = SetParentOperation(initializer, this); - } - public override IObjectOrCollectionInitializerOperation Initializer { get; } - } - - /// - /// Represents a type parameter object creation expression, i.e. new T(), where T is a type parameter with new constraint. - /// - internal abstract class LazyTypeParameterObjectCreationOperation : BaseTypeParameterObjectCreationOperation, ITypeParameterObjectCreationOperation - { - private IObjectOrCollectionInitializerOperation _lazyInitializerInterlocked = s_unsetObjectOrCollectionInitializer; - - public LazyTypeParameterObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); - - public override IObjectOrCollectionInitializerOperation Initializer - { - get - { - if (_lazyInitializerInterlocked == s_unsetObjectOrCollectionInitializer) - { - IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); - SetParentOperation(initializer, this); - Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unsetObjectOrCollectionInitializer); - } - - return _lazyInitializerInterlocked; - } - } - } - - /// - /// Represents a dynamically bound expression that can have argument names or refkinds. - /// - internal abstract partial class HasDynamicArgumentsExpression : Operation - { - protected HasDynamicArgumentsExpression(OperationKind operationKind, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(operationKind, semanticModel, syntax, type, constantValue, isImplicit) - { - ArgumentNames = argumentNames; - ArgumentRefKinds = argumentRefKinds; - } - - /// - /// Optional argument names for named arguments. - /// - public ImmutableArray ArgumentNames { get; } - /// - /// Optional argument ref kinds. - /// - public ImmutableArray ArgumentRefKinds { get; } - /// - /// Dynamically bound arguments, excluding the instance argument. - /// - public abstract ImmutableArray Arguments { get; } - } - - /// - /// Represents a dynamically bound new/New expression. - /// - internal abstract partial class BaseDynamicObjectCreationOperation : HasDynamicArgumentsExpression, IDynamicObjectCreationOperation - { - public BaseDynamicObjectCreationOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.DynamicObjectCreation, argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override IEnumerable Children - { - get - { - foreach (var argument in Arguments) - { - if (argument != null) - { - yield return argument; - } - } - if (Initializer != null) - { - yield return Initializer; - } - } - } - /// - /// Object or collection initializer, if any. - /// - public abstract IObjectOrCollectionInitializerOperation Initializer { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitDynamicObjectCreation(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitDynamicObjectCreation(this, argument); - } - } - - /// - /// Represents a dynamically bound new/New expression. - /// - internal sealed partial class DynamicObjectCreationOperation : BaseDynamicObjectCreationOperation, IDynamicObjectCreationOperation - { - public DynamicObjectCreationOperation(ImmutableArray arguments, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, IObjectOrCollectionInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) - { - Arguments = SetParentOperation(arguments, this); - Initializer = SetParentOperation(initializer, this); - } - public override ImmutableArray Arguments { get; } - public override IObjectOrCollectionInitializerOperation Initializer { get; } - } - - /// - /// Represents a dynamically bound new/New expression. - /// - internal abstract class LazyDynamicObjectCreationOperation : BaseDynamicObjectCreationOperation, IDynamicObjectCreationOperation - { - private ImmutableArray _lazyArgumentsInterlocked; - private IObjectOrCollectionInitializerOperation _lazyInitializerInterlocked = s_unsetObjectOrCollectionInitializer; - - public LazyDynamicObjectCreationOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateArguments(); - protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); - - public override ImmutableArray Arguments - { - get - { - if (_lazyArgumentsInterlocked.IsDefault) - { - ImmutableArray arguments = CreateArguments(); - SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); - } - - return _lazyArgumentsInterlocked; - } - } - - public override IObjectOrCollectionInitializerOperation Initializer - { - get - { - if (_lazyInitializerInterlocked == s_unsetObjectOrCollectionInitializer) - { - IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); - SetParentOperation(initializer, this); - Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unsetObjectOrCollectionInitializer); - } - - return _lazyInitializerInterlocked; - } - } - } - - /// - /// Represents a dynamically bound invocation expression in C# and late bound invocation in VB. - /// - internal abstract partial class BaseDynamicInvocationOperation : HasDynamicArgumentsExpression, IDynamicInvocationOperation - { - public BaseDynamicInvocationOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.DynamicInvocation, argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override IEnumerable Children - { - get - { - if (Operation != null) - { - yield return Operation; - } - foreach (var argument in Arguments) - { - if (argument != null) - { - yield return argument; - } - } - } - } - /// - /// Dynamically or late bound expression. - /// - public abstract IOperation Operation { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitDynamicInvocation(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitDynamicInvocation(this, argument); - } - } - - /// - /// Represents a dynamically bound invocation expression in C# and late bound invocation in VB. - /// - internal sealed partial class DynamicInvocationOperation : BaseDynamicInvocationOperation, IDynamicInvocationOperation - { - public DynamicInvocationOperation(IOperation operation, ImmutableArray arguments, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) - { - Operation = SetParentOperation(operation, this); - Arguments = SetParentOperation(arguments, this); - } - public override IOperation Operation { get; } - public override ImmutableArray Arguments { get; } - } - - /// - /// Represents a dynamically bound invocation expression in C# and late bound invocation in VB. - /// - internal abstract class LazyDynamicInvocationOperation : BaseDynamicInvocationOperation, IDynamicInvocationOperation - { - private IOperation _lazyOperationInterlocked = s_unset; - private ImmutableArray _lazyArgumentsInterlocked; - - public LazyDynamicInvocationOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperation(); - protected abstract ImmutableArray CreateArguments(); - - public override IOperation Operation - { - get - { - if (_lazyOperationInterlocked == s_unset) - { - IOperation operation = CreateOperation(); - SetParentOperation(operation, this); - Interlocked.CompareExchange(ref _lazyOperationInterlocked, operation, s_unset); - } - - return _lazyOperationInterlocked; - } - } - - public override ImmutableArray Arguments - { - get - { - if (_lazyArgumentsInterlocked.IsDefault) - { - ImmutableArray arguments = CreateArguments(); - SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); - } - - return _lazyArgumentsInterlocked; - } - } - } - - /// - /// Represents a dynamic indexer expression in C#. - /// - internal abstract partial class BaseDynamicIndexerAccessOperation : HasDynamicArgumentsExpression, IDynamicIndexerAccessOperation - { - public BaseDynamicIndexerAccessOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.DynamicIndexerAccess, argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override IEnumerable Children - { - get - { - if (Operation != null) - { - yield return Operation; - } - foreach (var argument in Arguments) - { - if (argument != null) - { - yield return argument; - } - } - } - } - /// - /// Dynamically indexed expression. - /// - public abstract IOperation Operation { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitDynamicIndexerAccess(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitDynamicIndexerAccess(this, argument); - } - } - - /// - /// Represents a dynamic indexer expression in C#. - /// - internal sealed partial class DynamicIndexerAccessOperation : BaseDynamicIndexerAccessOperation, IDynamicIndexerAccessOperation - { - public DynamicIndexerAccessOperation(IOperation operation, ImmutableArray arguments, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) - { - Operation = SetParentOperation(operation, this); - Arguments = SetParentOperation(arguments, this); - } - public override IOperation Operation { get; } - public override ImmutableArray Arguments { get; } - } - - /// - /// Represents a dynamic indexer expression in C#. - /// - internal abstract class LazyDynamicIndexerAccessOperation : BaseDynamicIndexerAccessOperation, IDynamicIndexerAccessOperation - { - private IOperation _lazyOperationInterlocked = s_unset; - private ImmutableArray _lazyArgumentsInterlocked; - - public LazyDynamicIndexerAccessOperation(ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(argumentNames, argumentRefKinds, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperation(); - protected abstract ImmutableArray CreateArguments(); - - public override IOperation Operation - { - get - { - if (_lazyOperationInterlocked == s_unset) - { - IOperation operation = CreateOperation(); - SetParentOperation(operation, this); - Interlocked.CompareExchange(ref _lazyOperationInterlocked, operation, s_unset); - } - - return _lazyOperationInterlocked; - } - } - - public override ImmutableArray Arguments - { - get - { - if (_lazyArgumentsInterlocked.IsDefault) - { - ImmutableArray arguments = CreateArguments(); - SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); - } - - return _lazyArgumentsInterlocked; - } - } - } - - /// - /// Represents an operation with one operand. - /// - internal abstract partial class BaseUnaryOperation : Operation, IUnaryOperation - { - protected BaseUnaryOperation(UnaryOperatorKind unaryOperationKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Unary, semanticModel, syntax, type, constantValue, isImplicit) - { - OperatorKind = unaryOperationKind; - IsLifted = isLifted; - IsChecked = isChecked; - OperatorMethod = operatorMethod; - } - /// - /// Kind of unary operation. - /// - public UnaryOperatorKind OperatorKind { get; } - /// - /// Operator method used by the operation, null if the operation does not use an operator method. - /// - public IMethodSymbol OperatorMethod { get; } - /// - /// if this is a 'lifted' binary operator. When there is an - /// operator that is defined to work on a value type, 'lifted' operators are - /// created to work on the versions of those - /// value types. - /// - public bool IsLifted { get; } - /// - /// if overflow checking is performed for the arithmetic operation. - /// - public bool IsChecked { get; } - public override IEnumerable Children - { - get - { - if (Operand != null) - { - yield return Operand; - } - } - } - /// - /// Single operand. - /// - public abstract IOperation Operand { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitUnaryOperator(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitUnaryOperator(this, argument); - } - } - - /// - /// Represents an operation with one operand. - /// - internal sealed partial class UnaryOperation : BaseUnaryOperation, IUnaryOperation - { - public UnaryOperation(UnaryOperatorKind unaryOperationKind, IOperation operand, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(unaryOperationKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) - { - Operand = SetParentOperation(operand, this); - } - - public override IOperation Operand { get; } - } - - /// - /// Represents an operation with one operand. - /// - internal abstract class LazyUnaryOperation : BaseUnaryOperation, IUnaryOperation - { - private IOperation _lazyOperandInterlocked = s_unset; - - public LazyUnaryOperation(UnaryOperatorKind unaryOperationKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(unaryOperationKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperand(); - - public override IOperation Operand - { - get - { - if (_lazyOperandInterlocked == s_unset) - { - IOperation operand = CreateOperand(); - SetParentOperation(operand, this); - Interlocked.CompareExchange(ref _lazyOperandInterlocked, operand, s_unset); - } - - return _lazyOperandInterlocked; - } - } - } - - /// - /// Represents a C# using or VB Using statement. - /// - internal abstract partial class BaseUsingOperation : Operation, IUsingOperation - { - protected BaseUsingOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.Using, semanticModel, syntax, type, constantValue, isImplicit) - { - Locals = locals; - } - public override IEnumerable Children - { - get - { - if (Resources != null) - { - yield return Resources; - } - if (Body != null) - { - yield return Body; - } - } - } - - /// - /// Declaration introduced or resource held by the using. - /// - public abstract IOperation Resources { get; } - - /// - /// Body of the using, over which the resources of the using are maintained. - /// - public abstract IOperation Body { get; } - - /// - /// Locals declared within the with scope spanning across this entire . - /// - public ImmutableArray Locals { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitUsing(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitUsing(this, argument); - } - } - - /// - /// Represents a C# using or VB Using statement. - /// - internal sealed partial class UsingOperation : BaseUsingOperation, IUsingOperation - { - public UsingOperation(IOperation resources, IOperation body, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, semanticModel, syntax, type, constantValue, isImplicit) - { - Resources = SetParentOperation(resources, this); - Body = SetParentOperation(body, this); - } - - public override IOperation Resources { get; } - public override IOperation Body { get; } - } - - /// - /// Represents a C# using or VB Using statement. - /// - internal abstract class LazyUsingOperation : BaseUsingOperation, IUsingOperation - { - private IOperation _lazyResourcesInterlocked = s_unset; - private IOperation _lazyBodyInterlocked = s_unset; - - public LazyUsingOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateResources(); - protected abstract IOperation CreateBody(); - - public override IOperation Resources - { - get - { - if (_lazyResourcesInterlocked == s_unset) - { - IOperation resources = CreateResources(); - SetParentOperation(resources, this); - Interlocked.CompareExchange(ref _lazyResourcesInterlocked, resources, s_unset); - } - - return _lazyResourcesInterlocked; - } - } - - public override IOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unset) - { - IOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unset); - } - - return _lazyBodyInterlocked; - } - } - } - - internal abstract partial class BaseVariableDeclaratorOperation : Operation, IVariableDeclaratorOperation - { - protected BaseVariableDeclaratorOperation(ILocalSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.VariableDeclarator, semanticModel, syntax, type, constantValue, isImplicit) - { - Symbol = symbol; - } - - public ILocalSymbol Symbol { get; } - /// - /// Optional initializer of the variable. - /// - public abstract IVariableInitializerOperation Initializer { get; } - public abstract ImmutableArray IgnoredArguments { get; } - - public override IEnumerable Children - { - get - { - foreach (var arg in IgnoredArguments) - { - yield return arg; - } - if (Initializer != null) - { - yield return Initializer; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitVariableDeclarator(this); - } - - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitVariableDeclarator(this, argument); - } - } - - /// - /// Represents a local variable declaration. - /// - internal sealed partial class VariableDeclaratorOperation : BaseVariableDeclaratorOperation - { - public VariableDeclaratorOperation(ILocalSymbol symbol, IVariableInitializerOperation initializer, ImmutableArray ignoredArguments, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(symbol, semanticModel, syntax, type, constantValue, isImplicit) - { - Initializer = SetParentOperation(initializer, this); - IgnoredArguments = SetParentOperation(ignoredArguments, this); - } - - public override IVariableInitializerOperation Initializer { get; } - public override ImmutableArray IgnoredArguments { get; } - } - - /// - /// Represents a local variable declaration. - /// - internal abstract class LazyVariableDeclaratorOperation : BaseVariableDeclaratorOperation - { - private IVariableInitializerOperation _lazyInitializerInterlocked = s_unsetVariableInitializer; - private ImmutableArray _lazyIgnoredArgumentsInterlocked; - - public LazyVariableDeclaratorOperation(ILocalSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(symbol, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IVariableInitializerOperation CreateInitializer(); - protected abstract ImmutableArray CreateIgnoredArguments(); - - public override IVariableInitializerOperation Initializer - { - get - { - if (_lazyInitializerInterlocked == s_unsetVariableInitializer) - { - IVariableInitializerOperation initializer = CreateInitializer(); - SetParentOperation(initializer, this); - Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unsetVariableInitializer); - } - - return _lazyInitializerInterlocked; - } - } - - public override ImmutableArray IgnoredArguments - { - get - { - if (_lazyIgnoredArgumentsInterlocked.IsDefault) - { - ImmutableArray ignoredArguments = CreateIgnoredArguments(); - SetParentOperation(ignoredArguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyIgnoredArgumentsInterlocked, ignoredArguments, default); - } - - return _lazyIgnoredArgumentsInterlocked; - } - } - } - - internal abstract partial class BaseVariableDeclarationOperation : Operation, IVariableDeclarationOperation - { - protected BaseVariableDeclarationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.VariableDeclaration, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public abstract ImmutableArray Declarators { get; } - - /// - /// Optional initializer of the variable. - /// - public abstract IVariableInitializerOperation Initializer { get; } - - public abstract ImmutableArray IgnoredDimensions { get; } - - public override IEnumerable Children - { - get - { - foreach (var dimension in IgnoredDimensions) - { - yield return dimension; - } - - foreach (var declaration in Declarators) - { - yield return declaration; - } - if (Initializer != null) - { - yield return Initializer; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitVariableDeclaration(this); - } - - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitVariableDeclaration(this, argument); - } - } - - internal sealed partial class VariableDeclarationOperation : BaseVariableDeclarationOperation - { - public VariableDeclarationOperation(ImmutableArray declarations, IVariableInitializerOperation initializer, ImmutableArray ignoredDimensions, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Declarators = SetParentOperation(declarations, this); - Initializer = SetParentOperation(initializer, this); - IgnoredDimensions = SetParentOperation(ignoredDimensions, this); - } - - public override ImmutableArray Declarators { get; } - public override IVariableInitializerOperation Initializer { get; } - public override ImmutableArray IgnoredDimensions { get; } - } - - internal abstract class LazyVariableDeclarationOperation : BaseVariableDeclarationOperation - { - private ImmutableArray _lazyDeclaratorsInterlocked; - private IVariableInitializerOperation _lazyInitializerInterlocked = s_unsetVariableInitializer; - private ImmutableArray _lazyIgnoredDimensionsInterlocked; - public LazyVariableDeclarationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateDeclarators(); - protected abstract IVariableInitializerOperation CreateInitializer(); - protected abstract ImmutableArray CreateIgnoredDimensions(); - - public override ImmutableArray Declarators - { - get - { - if (_lazyDeclaratorsInterlocked.IsDefault) - { - ImmutableArray declarators = CreateDeclarators(); - SetParentOperation(declarators, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDeclaratorsInterlocked, declarators, default); - } - - return _lazyDeclaratorsInterlocked; - } - } - - public override IVariableInitializerOperation Initializer - { - get - { - if (_lazyInitializerInterlocked == s_unsetVariableInitializer) - { - IVariableInitializerOperation initializer = CreateInitializer(); - SetParentOperation(initializer, this); - Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unsetVariableInitializer); - } - - return _lazyInitializerInterlocked; - } - } - - public override ImmutableArray IgnoredDimensions - { - get - { - if (_lazyIgnoredDimensionsInterlocked.IsDefault) - { - ImmutableArray ignoredDimensions = CreateIgnoredDimensions(); - SetParentOperation(ignoredDimensions, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyIgnoredDimensionsInterlocked, ignoredDimensions, default); - } - - return _lazyIgnoredDimensionsInterlocked; - } - } - } - - /// - /// Represents a local variable declaration statement. - /// - internal abstract partial class BaseVariableDeclarationGroupOperation : Operation, IVariableDeclarationGroupOperation - { - protected BaseVariableDeclarationGroupOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.VariableDeclarationGroup, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - foreach (var declaration in Declarations) - { - if (declaration != null) - { - yield return declaration; - } - } - } - } - /// - /// Variables declared by the statement. - /// - public abstract ImmutableArray Declarations { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitVariableDeclarationGroup(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitVariableDeclarationGroup(this, argument); - } - } - - /// - /// Represents a local variable declaration statement. - /// - internal sealed partial class VariableDeclarationGroupOperation : BaseVariableDeclarationGroupOperation, IVariableDeclarationGroupOperation - { - public VariableDeclarationGroupOperation(ImmutableArray declarations, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Declarations = SetParentOperation(declarations, this); - } - - public override ImmutableArray Declarations { get; } - } - - /// - /// Represents a local variable declaration statement. - /// - internal abstract class LazyVariableDeclarationGroupOperation : BaseVariableDeclarationGroupOperation, IVariableDeclarationGroupOperation - { - private ImmutableArray _lazyDeclarationsInterlocked; - - public LazyVariableDeclarationGroupOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateDeclarations(); - - public override ImmutableArray Declarations - { - get - { - if (_lazyDeclarationsInterlocked.IsDefault) - { - ImmutableArray declarations = CreateDeclarations(); - SetParentOperation(declarations, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDeclarationsInterlocked, declarations, default); - } - - return _lazyDeclarationsInterlocked; - } - } - } - - /// - /// Represents a while or do while loop. - /// - /// Current usage: - /// (1) C# 'while' and 'do while' loop statements. - /// (2) VB 'While', 'Do While' and 'Do Until' loop statements. - /// - /// - internal abstract partial class BaseWhileLoopOperation : LoopOperation, IWhileLoopOperation - { - public BaseWhileLoopOperation(ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, bool conditionIsTop, bool conditionIsUntil, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(LoopKind.While, locals, continueLabel, exitLabel, OperationKind.Loop, semanticModel, syntax, type, constantValue, isImplicit) - { - ConditionIsTop = conditionIsTop; - ConditionIsUntil = conditionIsUntil; - } - public override IEnumerable Children - { - get - { - if (ConditionIsTop) - { - if (Condition != null) - { - yield return Condition; - } - } - if (Body != null) - { - yield return Body; - } - if (!ConditionIsTop) - { - if (Condition != null) - { - yield return Condition; - } - } - if (IgnoredCondition != null) - { - yield return IgnoredCondition; - } - } - } - /// - /// Condition of the loop. - /// - public abstract IOperation Condition { get; } - /// - /// True if the is evaluated at start of each loop iteration. - /// False if it is evaluated at the end of each loop iteration. - /// - - public bool ConditionIsTop { get; } - - /// - /// True if the loop has 'Until' loop semantics and the loop is executed while is false. - /// - - public bool ConditionIsUntil { get; } - /// - /// Additional conditional supplied for loop in error cases, which is ignored by the compiler. - /// For example, for VB 'Do While' or 'Do Until' loop with syntax errors where both the top and bottom conditions are provided. - /// The top condition is preferred and exposed as and the bottom condition is ignored and exposed by this property. - /// This property should be null for all non-error cases. - /// - public abstract IOperation IgnoredCondition { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitWhileLoop(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitWhileLoop(this, argument); - } - } - - /// - /// Represents a while or do while loop. - /// - /// Current usage: - /// (1) C# 'while' and 'do while' loop statements. - /// (2) VB 'While', 'Do While' and 'Do Until' loop statements. - /// - /// - internal sealed partial class WhileLoopOperation : BaseWhileLoopOperation, IWhileLoopOperation - { - public WhileLoopOperation(IOperation condition, IOperation body, IOperation ignoredCondition, ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, bool conditionIsTop, bool conditionIsUntil, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, continueLabel, exitLabel, conditionIsTop, conditionIsUntil, semanticModel, syntax, type, constantValue, isImplicit) - { - Condition = SetParentOperation(condition, this); - Body = SetParentOperation(body, this); - IgnoredCondition = SetParentOperation(ignoredCondition, this); - } - public override IOperation Condition { get; } - public override IOperation Body { get; } - public override IOperation IgnoredCondition { get; } - } - - /// - /// Represents a while or do while loop. - /// - /// Current usage: - /// (1) C# 'while' and 'do while' loop statements. - /// (2) VB 'While', 'Do While' and 'Do Until' loop statements. - /// - /// - internal abstract class LazyWhileLoopOperation : BaseWhileLoopOperation, IWhileLoopOperation - { - private IOperation _lazyConditionInterlocked = s_unset; - private IOperation _lazyBodyInterlocked = s_unset; - private IOperation _lazyIgnoredConditionInterlocked = s_unset; - - public LazyWhileLoopOperation(ImmutableArray locals, ILabelSymbol continueLabel, ILabelSymbol exitLabel, bool conditionIsTop, bool conditionIsUntil, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(locals, continueLabel, exitLabel, conditionIsTop, conditionIsUntil, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateCondition(); - protected abstract IOperation CreateBody(); - protected abstract IOperation CreateIgnoredCondition(); - - public override IOperation Condition - { - get - { - if (_lazyConditionInterlocked == s_unset) - { - IOperation condition = CreateCondition(); - SetParentOperation(condition, this); - Interlocked.CompareExchange(ref _lazyConditionInterlocked, condition, s_unset); - } - - return _lazyConditionInterlocked; - } - } - - public override IOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unset) - { - IOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unset); - } - - return _lazyBodyInterlocked; - } - } - - public override IOperation IgnoredCondition - { - get - { - if (_lazyIgnoredConditionInterlocked == s_unset) - { - IOperation ignoredCondition = CreateIgnoredCondition(); - SetParentOperation(ignoredCondition, this); - Interlocked.CompareExchange(ref _lazyIgnoredConditionInterlocked, ignoredCondition, s_unset); - } - - return _lazyIgnoredConditionInterlocked; - } - } - } - - /// - /// Represents a VB With statement. - /// - internal abstract partial class BaseWithOperation : Operation, IWithOperation - { - protected BaseWithOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - // https://github.com/dotnet/roslyn/issues/22005 - // base(OperationKind.With, semanticModel, syntax, type, constantValue, isImplicit) - base(OperationKind.None, semanticModel, syntax, type, constantValue, isImplicit) - { - } - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - if (Body != null) - { - yield return Body; - } - } - } - /// - /// Body of the with. - /// - public abstract IOperation Body { get; } - /// - /// Value to whose members leading-dot-qualified references within the with body bind. - /// - public abstract IOperation Value { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitWith(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitWith(this, argument); - } - } - - /// - /// Represents a VB With statement. - /// - internal sealed partial class WithOperation : BaseWithOperation, IWithOperation - { - public WithOperation(IOperation body, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Body = SetParentOperation(body, this); - Value = SetParentOperation(value, this); - } - - public override IOperation Body { get; } - public override IOperation Value { get; } - } - - /// - /// Represents a VB With statement. - /// - internal abstract class LazyWithOperation : BaseWithOperation, IWithOperation - { - private IOperation _lazyBodyInterlocked = s_unset; - private IOperation _lazyValueInterlocked = s_unset; - - public LazyWithOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateBody(); - protected abstract IOperation CreateValue(); - - public override IOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unset) - { - IOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unset); - } - - return _lazyBodyInterlocked; - } - } - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents a local function statement. - /// - internal abstract partial class BaseLocalFunctionOperation : Operation, ILocalFunctionOperation - { - protected BaseLocalFunctionOperation(IMethodSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.LocalFunction, semanticModel, syntax, type, constantValue, isImplicit) - { - Symbol = symbol; - } - /// - /// Local function symbol. - /// - public IMethodSymbol Symbol { get; } - public override IEnumerable Children - { - get - { - if (Body != null) - { - yield return Body; - } - if (IgnoredBody != null) - { - yield return IgnoredBody; - } - } - } - - /// - /// Body of the local function. - /// - public abstract IBlockOperation Body { get; } - public abstract IBlockOperation IgnoredBody { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitLocalFunction(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitLocalFunction(this, argument); - } - } - - /// - /// Represents a local function statement. - /// - internal sealed partial class LocalFunctionOperation : BaseLocalFunctionOperation, ILocalFunctionOperation - { - public LocalFunctionOperation(IMethodSymbol symbol, IBlockOperation body, IBlockOperation ignoredBody, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(symbol, semanticModel, syntax, type, constantValue, isImplicit) - { - Body = SetParentOperation(body, this); - IgnoredBody = SetParentOperation(ignoredBody, this); - } - - public override IBlockOperation Body { get; } - public override IBlockOperation IgnoredBody { get; } - } - - /// - /// Represents a local function statement. - /// - internal abstract class LazyLocalFunctionOperation : BaseLocalFunctionOperation, ILocalFunctionOperation - { - private IBlockOperation _lazyBodyInterlocked = s_unsetBlock; - private IBlockOperation _lazyIgnoredBodyInterlocked = s_unsetBlock; - - public LazyLocalFunctionOperation(IMethodSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(symbol, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IBlockOperation CreateBody(); - protected abstract IBlockOperation CreateIgnoredBody(); - - public override IBlockOperation Body - { - get - { - if (_lazyBodyInterlocked == s_unsetBlock) - { - IBlockOperation body = CreateBody(); - SetParentOperation(body, this); - Interlocked.CompareExchange(ref _lazyBodyInterlocked, body, s_unsetBlock); - } - - return _lazyBodyInterlocked; - } - } - - public override IBlockOperation IgnoredBody - { - get - { - if (_lazyIgnoredBodyInterlocked == s_unsetBlock) - { - IBlockOperation ignoredBody = CreateIgnoredBody(); - SetParentOperation(ignoredBody, this); - Interlocked.CompareExchange(ref _lazyIgnoredBodyInterlocked, ignoredBody, s_unsetBlock); - } - - return _lazyIgnoredBodyInterlocked; - } - } - } - - /// - /// Represents a C# constant pattern. - /// - internal abstract partial class BaseConstantPatternOperation : Operation, IConstantPatternOperation - { - protected BaseConstantPatternOperation(ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : - base(OperationKind.ConstantPattern, semanticModel, syntax, type: default, constantValue: default, isImplicit) - { - InputType = inputType; - } - - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - } - } - /// - /// Constant value of the pattern. - /// - public abstract IOperation Value { get; } - - public ITypeSymbol InputType { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitConstantPattern(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitConstantPattern(this, argument); - } - } - - /// - /// Represents a C# constant pattern. - /// - internal sealed partial class ConstantPatternOperation : BaseConstantPatternOperation, IConstantPatternOperation - { - public ConstantPatternOperation(ITypeSymbol inputType, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : - base(inputType, semanticModel, syntax, isImplicit) - { - Value = SetParentOperation(value, this); - } - - public override IOperation Value { get; } - } - - /// - /// Represents a C# constant pattern. - /// - internal abstract class LazyConstantPatternOperation : BaseConstantPatternOperation, IConstantPatternOperation - { - private IOperation _lazyValueInterlocked = s_unset; - - public LazyConstantPatternOperation(ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : - base(inputType, semanticModel, syntax, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - } - - /// - /// Represents a C# declaration pattern. - /// - internal sealed partial class DeclarationPatternOperation : BasePatternOperation, IDeclarationPatternOperation - { - public DeclarationPatternOperation( - ITypeSymbol inputType, - ITypeSymbol matchedType, - ISymbol declaredSymbol, - bool matchesNull, - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : this(matchedType, matchesNull, declaredSymbol, inputType, semanticModel, syntax, type: default, constantValue: default, isImplicit) - { } - } - - internal abstract partial class BaseRecursivePatternOperation : Operation, IRecursivePatternOperation - { - public BaseRecursivePatternOperation( - ITypeSymbol inputType, - ITypeSymbol matchedType, - ISymbol deconstructSymbol, - ISymbol declaredSymbol, - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(OperationKind.RecursivePattern, semanticModel, syntax, type: default, constantValue: default, isImplicit) - { - InputType = inputType; - MatchedType = matchedType; - DeconstructSymbol = deconstructSymbol; - DeclaredSymbol = declaredSymbol; - } - public ITypeSymbol InputType { get; } - public ITypeSymbol MatchedType { get; } - public ISymbol DeconstructSymbol { get; } - public abstract ImmutableArray DeconstructionSubpatterns { get; } - public abstract ImmutableArray PropertySubpatterns { get; } - public ISymbol DeclaredSymbol { get; } - public override IEnumerable Children - { - get - { - foreach (var p in DeconstructionSubpatterns) - { - yield return p; - } - - foreach (var p in PropertySubpatterns) - { - yield return p; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitRecursivePattern(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitRecursivePattern(this, argument); - } - } - - /// - /// Represents a C# recursive pattern. - /// - internal sealed partial class RecursivePatternOperation : BaseRecursivePatternOperation - { - public RecursivePatternOperation( - ITypeSymbol inputType, - ITypeSymbol matchedType, - ISymbol deconstructSymbol, - ImmutableArray deconstructionSubpatterns, - ImmutableArray propertySubpatterns, - ISymbol declaredSymbol, SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(inputType, matchedType, deconstructSymbol, declaredSymbol, semanticModel, syntax, isImplicit) - { - SetParentOperation(deconstructionSubpatterns, this); - DeconstructionSubpatterns = deconstructionSubpatterns; - SetParentOperation(propertySubpatterns, this); - PropertySubpatterns = propertySubpatterns; - } - public override ImmutableArray DeconstructionSubpatterns { get; } - public override ImmutableArray PropertySubpatterns { get; } - } - - internal abstract partial class LazyRecursivePatternOperation : BaseRecursivePatternOperation - { - private ImmutableArray _lazyDeconstructionSubpatterns; - private ImmutableArray _lazyPropertySubpatterns; - public LazyRecursivePatternOperation( - ITypeSymbol inputType, - ITypeSymbol matchedType, - ISymbol deconstructSymbol, - ISymbol declaredSymbol, - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(inputType, matchedType, deconstructSymbol, declaredSymbol, semanticModel, syntax, isImplicit) - { - } - public abstract ImmutableArray CreateDeconstructionSubpatterns(); - public abstract ImmutableArray CreatePropertySubpatterns(); - public override ImmutableArray DeconstructionSubpatterns - { - get - { - if (_lazyDeconstructionSubpatterns.IsDefault) - { - var deconstructionSubpatterns = CreateDeconstructionSubpatterns(); - foreach (var d in deconstructionSubpatterns) - { - SetParentOperation(d, this); - } - - ImmutableInterlocked.InterlockedInitialize(ref _lazyDeconstructionSubpatterns, deconstructionSubpatterns); - } - - return _lazyDeconstructionSubpatterns; - } - } - public override ImmutableArray PropertySubpatterns - { - get - { - if (_lazyPropertySubpatterns.IsDefault) - { - var propertySubpatterns = CreatePropertySubpatterns(); - foreach (var propertySubpattern in propertySubpatterns) - { - SetParentOperation(propertySubpattern, this); - } - - ImmutableInterlocked.InterlockedInitialize(ref _lazyPropertySubpatterns, propertySubpatterns); - } - - return _lazyPropertySubpatterns; - } - } - } - - internal abstract partial class BasePropertySubpatternOperation : Operation, IPropertySubpatternOperation - { - public BasePropertySubpatternOperation( - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(OperationKind.PropertySubpattern, semanticModel, syntax, type: default, constantValue: default, isImplicit) - { - } - public abstract IOperation Member { get; } - public abstract IPatternOperation Pattern { get; } - public override IEnumerable Children - { - get - { - if (Member != null) - yield return Member; - - if (Pattern != null) - yield return Pattern; - } - } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitPropertySubpattern(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitPropertySubpattern(this, argument); - } - } - - internal sealed partial class PropertySubpatternOperation : BasePropertySubpatternOperation - { - public PropertySubpatternOperation( - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit, - IOperation member, - IPatternOperation pattern) - : base(semanticModel, syntax, isImplicit) - { - SetParentOperation(member, this); - Member = member; - SetParentOperation(pattern, this); - Pattern = pattern; - } - public override IOperation Member { get; } - public override IPatternOperation Pattern { get; } - } - - internal abstract partial class LazyPropertySubpatternOperation : BasePropertySubpatternOperation - { - private IOperation _lazyMember = s_unset; - private IPatternOperation _lazyPattern = s_unsetPattern; - public LazyPropertySubpatternOperation( - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(semanticModel, syntax, isImplicit) - { - } - public abstract IOperation CreateMember(); - public abstract IPatternOperation CreatePattern(); - public override IOperation Member - { - get - { - if (_lazyMember == s_unset) - { - var member = CreateMember(); - SetParentOperation(member, this); - Interlocked.CompareExchange(ref _lazyMember, member, s_unset); - } - - return _lazyMember; - } - } - public override IPatternOperation Pattern - { - get - { - if (_lazyPattern == s_unsetPattern) - { - var pattern = CreatePattern(); - SetParentOperation(pattern, this); - Interlocked.CompareExchange(ref _lazyPattern, pattern, s_unsetPattern); - } - - return _lazyPattern; - } - } - } - - /// - /// Represents a C# pattern case clause. - /// - internal abstract partial class BasePatternCaseClauseOperation : BaseCaseClauseOperation, IPatternCaseClauseOperation - { - protected BasePatternCaseClauseOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(CaseKind.Pattern, label, OperationKind.CaseClause, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Pattern != null) - { - yield return Pattern; - } - if (Guard != null) - { - yield return Guard; - } - } - } - /// - /// Pattern associated with case clause. - /// - public abstract IPatternOperation Pattern { get; } - /// - /// Guard expression associated with the pattern case clause. - /// - public abstract IOperation Guard { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitPatternCaseClause(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitPatternCaseClause(this, argument); - } - } - - /// - /// Represents a C# pattern case clause. - /// - internal sealed partial class PatternCaseClauseOperation : BasePatternCaseClauseOperation, IPatternCaseClauseOperation - { - public PatternCaseClauseOperation(ILabelSymbol label, IPatternOperation pattern, IOperation guardExpression, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(label, semanticModel, syntax, type, constantValue, isImplicit) - { - Pattern = SetParentOperation(pattern, this); - Guard = SetParentOperation(guardExpression, this); - } - - public override IPatternOperation Pattern { get; } - public override IOperation Guard { get; } - } - - /// - /// Represents a C# pattern case clause. - /// - internal abstract class LazyPatternCaseClauseOperation : BasePatternCaseClauseOperation, IPatternCaseClauseOperation - { - private IPatternOperation _lazyPatternInterlocked = s_unsetPattern; - private IOperation _lazyGuardExpressionInterlocked = s_unset; - - public LazyPatternCaseClauseOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(label, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IPatternOperation CreatePattern(); - protected abstract IOperation CreateGuard(); - - public override IPatternOperation Pattern - { - get - { - if (_lazyPatternInterlocked == s_unsetPattern) - { - IPatternOperation pattern = CreatePattern(); - SetParentOperation(pattern, this); - Interlocked.CompareExchange(ref _lazyPatternInterlocked, pattern, s_unsetPattern); - } - - return _lazyPatternInterlocked; - } - } - - public override IOperation Guard - { - get - { - if (_lazyGuardExpressionInterlocked == s_unset) - { - IOperation guard = CreateGuard(); - SetParentOperation(guard, this); - Interlocked.CompareExchange(ref _lazyGuardExpressionInterlocked, guard, s_unset); - } - - return _lazyGuardExpressionInterlocked; - } - } - } - - /// - /// Represents a C# switch expression. - /// - internal abstract partial class BaseSwitchExpressionOperation : Operation, ISwitchExpressionOperation - { - public BaseSwitchExpressionOperation( - ITypeSymbol type, - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(OperationKind.SwitchExpression, semanticModel, syntax, type: type, constantValue: default, isImplicit) - { - } - public abstract IOperation Value { get; } - public abstract ImmutableArray Arms { get; } - public override IEnumerable Children - { - get - { - yield return Value; - foreach (var arm in Arms) - { - yield return arm; - } - } - } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitSwitchExpression(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitSwitchExpression(this, argument); - } - } - - internal sealed partial class SwitchExpressionOperation : BaseSwitchExpressionOperation - { - public SwitchExpressionOperation( - ITypeSymbol type, - IOperation value, - ImmutableArray arms, - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(type, semanticModel, syntax, isImplicit) - { - Value = SetParentOperation(value, this); - Arms = SetParentOperation(arms, this); - } - public override IOperation Value { get; } - public override ImmutableArray Arms { get; } - } - - internal abstract partial class LazySwitchExpressionOperation : BaseSwitchExpressionOperation - { - private IOperation _lazyValue = s_unset; - private ImmutableArray _lazyArms = default; - public LazySwitchExpressionOperation( - ITypeSymbol type, - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(type, semanticModel, syntax, isImplicit) - { - } - protected abstract IOperation CreateValue(); - protected abstract ImmutableArray CreateArms(); - public override IOperation Value - { - get - { - if (_lazyValue == s_unset) - { - var value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValue, value, s_unset); - } - - return _lazyValue; - } - } - public override ImmutableArray Arms - { - get - { - if (_lazyArms.IsDefault) - { - var arms = CreateArms(); - SetParentOperation(arms, this); - ImmutableInterlocked.InterlockedInitialize(ref _lazyArms, arms); - } - - return _lazyArms; - } - } - } - - /// - /// Represents a C# switch expression arm. - /// - internal abstract partial class BaseSwitchExpressionArmOperation : Operation, ISwitchExpressionArmOperation - { - public BaseSwitchExpressionArmOperation( - ImmutableArray locals, - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(OperationKind.SwitchExpressionArm, semanticModel, syntax, type: default, constantValue: default, isImplicit) - { - this.Locals = locals; - } - public ImmutableArray Locals { get; } - public abstract IPatternOperation Pattern { get; } - public abstract IOperation Guard { get; } - public abstract IOperation Value { get; } - - public override IEnumerable Children - { - get - { - yield return Pattern; - if (Guard != null) - yield return Guard; - yield return Value; - } - } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitSwitchExpressionArm(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitSwitchExpressionArm(this, argument); - } - } - - internal sealed partial class SwitchExpressionArmOperation : BaseSwitchExpressionArmOperation - { - public SwitchExpressionArmOperation( - ImmutableArray locals, - IPatternOperation pattern, - IOperation guard, - IOperation value, - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(locals, semanticModel, syntax, isImplicit) - { - Pattern = SetParentOperation(pattern, this); - Guard = SetParentOperation(guard, this); - Value = SetParentOperation(value, this); - } - public sealed override IPatternOperation Pattern { get; } - public sealed override IOperation Guard { get; } - public sealed override IOperation Value { get; } - } - - internal abstract partial class LazySwitchExpressionArmOperation : BaseSwitchExpressionArmOperation - { - private IPatternOperation _lazyPattern = s_unsetPattern; - private IOperation _lazyGuard = s_unset; - private IOperation _lazyValue = s_unset; - public LazySwitchExpressionArmOperation( - ImmutableArray locals, - SemanticModel semanticModel, - SyntaxNode syntax, - bool isImplicit) - : base(locals, semanticModel, syntax, isImplicit) - { - } - protected abstract IPatternOperation CreatePattern(); - protected abstract IOperation CreateGuard(); - protected abstract IOperation CreateValue(); - public override IPatternOperation Pattern - { - get - { - if (_lazyPattern == s_unsetPattern) - { - var pattern = CreatePattern(); - SetParentOperation(pattern, this); - Interlocked.CompareExchange(ref _lazyPattern, pattern, s_unsetPattern); - } - - return _lazyPattern; - } - } - public override IOperation Guard - { - get - { - if (_lazyGuard == s_unset) - { - var guard = CreateGuard(); - SetParentOperation(guard, this); - Interlocked.CompareExchange(ref _lazyGuard, guard, s_unset); - } - - return _lazyGuard; - } - } - public override IOperation Value - { - get - { - if (_lazyValue == s_unset) - { - var value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValue, value, s_unset); - } - - return _lazyValue; - } - } - } - - /// - /// Represents a C# is pattern expression. For example, "x is int i". - /// - internal abstract partial class BaseIsPatternOperation : Operation, IIsPatternOperation - { - protected BaseIsPatternOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.IsPattern, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Value != null) - { - yield return Value; - } - if (Pattern != null) - { - yield return Pattern; - } - } - } - /// - /// Expression. - /// - public abstract IOperation Value { get; } - /// - /// Pattern. - /// - public abstract IPatternOperation Pattern { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitIsPattern(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitIsPattern(this, argument); - } - } - - /// - /// Represents a C# is pattern expression. For example, "x is int i". - /// - internal sealed partial class IsPatternOperation : BaseIsPatternOperation, IIsPatternOperation - { - public IsPatternOperation(IOperation value, IPatternOperation pattern, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Value = SetParentOperation(value, this); - Pattern = SetParentOperation(pattern, this); - } - - public override IOperation Value { get; } - public override IPatternOperation Pattern { get; } - } - - /// - /// Represents a C# is pattern expression. For example, "x is int i". - /// - internal abstract class LazyIsPatternOperation : BaseIsPatternOperation, IIsPatternOperation - { - private IOperation _lazyValueInterlocked = s_unset; - private IPatternOperation _lazyPatternInterlocked = s_unsetPattern; - - public LazyIsPatternOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateValue(); - protected abstract IPatternOperation CreatePattern(); - - public override IOperation Value - { - get - { - if (_lazyValueInterlocked == s_unset) - { - IOperation value = CreateValue(); - SetParentOperation(value, this); - Interlocked.CompareExchange(ref _lazyValueInterlocked, value, s_unset); - } - - return _lazyValueInterlocked; - } - } - - public override IPatternOperation Pattern - { - get - { - if (_lazyPatternInterlocked == s_unsetPattern) - { - IPatternOperation pattern = CreatePattern(); - SetParentOperation(pattern, this); - Interlocked.CompareExchange(ref _lazyPatternInterlocked, pattern, s_unsetPattern); - } - - return _lazyPatternInterlocked; - } - } - } - - /// - /// Represents a C# or VB object or collection initializer expression. - /// - internal abstract partial class BaseObjectOrCollectionInitializerOperation : Operation, IObjectOrCollectionInitializerOperation - { - protected BaseObjectOrCollectionInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.ObjectOrCollectionInitializer, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - foreach (var initializer in Initializers) - { - if (initializer != null) - { - yield return initializer; - } - } - } - } - /// - /// Object member or collection initializers. - /// - public abstract ImmutableArray Initializers { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitObjectOrCollectionInitializer(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitObjectOrCollectionInitializer(this, argument); - } - } - - /// - /// Represents a C# or VB object or collection initializer expression. - /// - internal sealed partial class ObjectOrCollectionInitializerOperation : BaseObjectOrCollectionInitializerOperation, IObjectOrCollectionInitializerOperation - { - public ObjectOrCollectionInitializerOperation(ImmutableArray initializers, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Initializers = SetParentOperation(initializers, this); - } - - public override ImmutableArray Initializers { get; } - } - - /// - /// Represents a C# or VB object or collection initializer expression. - /// - internal abstract class LazyObjectOrCollectionInitializerOperation : BaseObjectOrCollectionInitializerOperation, IObjectOrCollectionInitializerOperation - { - private ImmutableArray _lazyInitializersInterlocked; - - public LazyObjectOrCollectionInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract ImmutableArray CreateInitializers(); - - public override ImmutableArray Initializers - { - get - { - if (_lazyInitializersInterlocked.IsDefault) - { - ImmutableArray initializers = CreateInitializers(); - SetParentOperation(initializers, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyInitializersInterlocked, initializers, default); - } - - return _lazyInitializersInterlocked; - } - } - } - - /// - /// Represents a C# or VB member initializer expression within an object initializer expression. - /// - internal abstract partial class BaseMemberInitializerOperation : Operation, IMemberInitializerOperation - { - protected BaseMemberInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.MemberInitializer, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (InitializedMember != null) - { - yield return InitializedMember; - } - if (Initializer != null) - { - yield return Initializer; - } - } - } - /// - /// Initialized member. - /// - public abstract IOperation InitializedMember { get; } - - /// - /// Member initializer. - /// - public abstract IObjectOrCollectionInitializerOperation Initializer { get; } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitMemberInitializer(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitMemberInitializer(this, argument); - } - } - - /// - /// Represents a C# or VB member initializer expression within an object initializer expression. - /// - internal sealed partial class MemberInitializerOperation : BaseMemberInitializerOperation, IMemberInitializerOperation - { - public MemberInitializerOperation(IOperation initializedMember, IObjectOrCollectionInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - InitializedMember = SetParentOperation(initializedMember, this); - Initializer = SetParentOperation(initializer, this); - } - - public override IOperation InitializedMember { get; } - public override IObjectOrCollectionInitializerOperation Initializer { get; } - } - - /// - /// Represents a C# or VB member initializer expression within an object initializer expression. - /// - internal abstract class LazyMemberInitializerOperation : BaseMemberInitializerOperation, IMemberInitializerOperation - { - private IOperation _lazyInitializedMemberInterlocked = s_unset; - private IObjectOrCollectionInitializerOperation _lazyInitializerInterlocked = s_unsetObjectOrCollectionInitializer; - - public LazyMemberInitializerOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateInitializedMember(); - protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); - - public override IOperation InitializedMember - { - get - { - if (_lazyInitializedMemberInterlocked == s_unset) - { - IOperation initializedMember = CreateInitializedMember(); - SetParentOperation(initializedMember, this); - Interlocked.CompareExchange(ref _lazyInitializedMemberInterlocked, initializedMember, s_unset); - } - - return _lazyInitializedMemberInterlocked; - } - } - - public override IObjectOrCollectionInitializerOperation Initializer - { - get - { - if (_lazyInitializerInterlocked == s_unsetObjectOrCollectionInitializer) - { - IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); - SetParentOperation(initializer, this); - Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unsetObjectOrCollectionInitializer); - } - - return _lazyInitializerInterlocked; - } - } - } - - /// - /// Represents an unrolled/lowered query expression in C# and VB. - /// For example, for the query expression "from x in set where x.Name != null select x.Name", the Operation tree has the following shape: - /// ITranslatedQueryExpression - /// IInvocationExpression ('Select' invocation for "select x.Name") - /// IInvocationExpression ('Where' invocation for "where x.Name != null") - /// IInvocationExpression ('From' invocation for "from x in set") - /// - internal abstract partial class BaseTranslatedQueryOperation : Operation, ITranslatedQueryOperation - { - protected BaseTranslatedQueryOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.TranslatedQuery, semanticModel, syntax, type, constantValue, isImplicit) - { - } - /// - /// Underlying unrolled expression. - /// - public abstract IOperation Operation { get; } - public override IEnumerable Children - { - get - { - if (Operation != null) - { - yield return Operation; - } - } - } - public override void Accept(OperationVisitor visitor) - { - visitor.VisitTranslatedQuery(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitTranslatedQuery(this, argument); - } - } - - /// - /// Represents an unrolled/lowered query expression in C# and VB. - /// For example, for the query expression "from x in set where x.Name != null select x.Name", the Operation tree has the following shape: - /// ITranslatedQueryExpression - /// IInvocationExpression ('Select' invocation for "select x.Name") - /// IInvocationExpression ('Where' invocation for "where x.Name != null") - /// IInvocationExpression ('From' invocation for "from x in set") - /// - internal sealed partial class TranslatedQueryOperation : BaseTranslatedQueryOperation, ITranslatedQueryOperation - { - public TranslatedQueryOperation(IOperation operation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Operation = SetParentOperation(operation, this); - } - public override IOperation Operation { get; } - } - - /// - /// Represents an unrolled/lowered query expression in C# and VB. - /// For example, for the query expression "from x in set where x.Name != null select x.Name", the Operation tree has the following shape: - /// ITranslatedQueryExpression - /// IInvocationExpression ('Select' invocation for "select x.Name") - /// IInvocationExpression ('Where' invocation for "where x.Name != null") - /// IInvocationExpression ('From' invocation for "from x in set") - /// - internal abstract class LazyTranslatedQueryOperation : BaseTranslatedQueryOperation, ITranslatedQueryOperation - { - private IOperation _lazyOperationInterlocked = s_unset; - - public LazyTranslatedQueryOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateOperation(); - - public override IOperation Operation - { - get - { - if (_lazyOperationInterlocked == s_unset) - { - IOperation operation = CreateOperation(); - SetParentOperation(operation, this); - Interlocked.CompareExchange(ref _lazyOperationInterlocked, operation, s_unset); - } - - return _lazyOperationInterlocked; - } - } - } - - internal sealed partial class FlowCaptureReferenceOperation : Operation, IFlowCaptureReferenceOperation - { - public FlowCaptureReferenceOperation(int id, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : - base(OperationKind.FlowCaptureReference, semanticModel: null, syntax: syntax, type: type, constantValue: constantValue, isImplicit: true) - { - Id = new CaptureId(id); - } - - public FlowCaptureReferenceOperation(CaptureId id, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : - base(OperationKind.FlowCaptureReference, semanticModel: null, syntax: syntax, type: type, constantValue: constantValue, isImplicit: true) - { - Id = id; - } - } - - internal sealed partial class FlowCaptureOperation : Operation, IFlowCaptureOperation - { - public FlowCaptureOperation(int id, SyntaxNode syntax, IOperation value) : - base(OperationKind.FlowCapture, semanticModel: null, syntax: syntax, type: null, constantValue: default, isImplicit: true) - { - Debug.Assert(value != null); - Id = new CaptureId(id); - Value = SetParentOperation(value, this); - } - - public CaptureId Id { get; } - public IOperation Value { get; } - public override IEnumerable Children - { - get - { - yield return Value; - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitFlowCapture(this); - } - - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitFlowCapture(this, argument); - } - } - - internal sealed partial class IsNullOperation : Operation, IIsNullOperation - { - public IsNullOperation(SyntaxNode syntax, IOperation operand, ITypeSymbol type, Optional constantValue) : - base(OperationKind.IsNull, semanticModel: null, syntax: syntax, type: type, constantValue: constantValue, isImplicit: true) - { - Debug.Assert(operand != null); - Operand = SetParentOperation(operand, this); - } - - public IOperation Operand { get; } - public override IEnumerable Children - { - get - { - yield return Operand; - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitIsNull(this); - } - - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitIsNull(this, argument); - } - } - - internal sealed partial class CaughtExceptionOperation : Operation, ICaughtExceptionOperation - { - public CaughtExceptionOperation(SyntaxNode syntax, ITypeSymbol type) : - this(semanticModel: null, syntax: syntax, type: type, constantValue: default, isImplicit: true) - { - } - } - - internal sealed partial class StaticLocalInitializationSemaphoreOperation : Operation, IStaticLocalInitializationSemaphoreOperation - { - public StaticLocalInitializationSemaphoreOperation(ILocalSymbol local, SyntaxNode syntax, ITypeSymbol type) : - base(OperationKind.StaticLocalInitializationSemaphore, semanticModel: null, syntax, type, constantValue: default, isImplicit: true) - { - Local = local; - } - } - - internal abstract class BaseMethodBodyBaseOperation : Operation, IMethodBodyBaseOperation - { - protected BaseMethodBodyBaseOperation(OperationKind kind, SemanticModel semanticModel, SyntaxNode syntax) : - base(kind, semanticModel, syntax, type: null, constantValue: default, isImplicit: false) - { - } - - public abstract IBlockOperation BlockBody { get; } - public abstract IBlockOperation ExpressionBody { get; } - public abstract override IEnumerable Children { get; } - } - - internal abstract class BaseMethodBodyOperation : BaseMethodBodyBaseOperation, IMethodBodyOperation - { - protected BaseMethodBodyOperation(SemanticModel semanticModel, SyntaxNode syntax) : - base(OperationKind.MethodBody, semanticModel, syntax) - { - } - - public sealed override IEnumerable Children - { - get - { - IBlockOperation blockBody = BlockBody; - if (blockBody != null) - { - yield return blockBody; - } - - IBlockOperation expressionBody = ExpressionBody; - if (expressionBody != null) - { - yield return expressionBody; - } - } - } - - public sealed override void Accept(OperationVisitor visitor) - { - visitor.VisitMethodBodyOperation(this); - } - - public sealed override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitMethodBodyOperation(this, argument); - } - } - - internal sealed class MethodBodyOperation : BaseMethodBodyOperation - { - public MethodBodyOperation(SemanticModel semanticModel, SyntaxNode syntax, IBlockOperation blockBody, IBlockOperation expressionBody) : - base(semanticModel, syntax) - { - BlockBody = SetParentOperation(blockBody, this); - ExpressionBody = SetParentOperation(expressionBody, this); - } - - public override IBlockOperation BlockBody { get; } - public override IBlockOperation ExpressionBody { get; } - } - - internal abstract class LazyMethodBodyOperation : BaseMethodBodyOperation - { - private IBlockOperation _lazyBlockBodyInterlocked = s_unsetBlock; - private IBlockOperation _lazyExpressionBodyInterlocked = s_unsetBlock; - - public LazyMethodBodyOperation(SemanticModel semanticModel, SyntaxNode syntax) : - base(semanticModel, syntax) - { - } - - protected abstract IBlockOperation CreateBlockBody(); - protected abstract IBlockOperation CreateExpressionBody(); - - public override IBlockOperation BlockBody - { - get - { - if (_lazyBlockBodyInterlocked == s_unsetBlock) - { - IBlockOperation blockBody = CreateBlockBody(); - SetParentOperation(blockBody, this); - Interlocked.CompareExchange(ref _lazyBlockBodyInterlocked, blockBody, s_unsetBlock); - } - - return _lazyBlockBodyInterlocked; - } - } - - public override IBlockOperation ExpressionBody - { - get - { - if (_lazyExpressionBodyInterlocked == s_unsetBlock) - { - IBlockOperation expressionBody = CreateExpressionBody(); - SetParentOperation(expressionBody, this); - Interlocked.CompareExchange(ref _lazyExpressionBodyInterlocked, expressionBody, s_unsetBlock); - } - - return _lazyExpressionBodyInterlocked; - } - } - } - - internal abstract class BaseConstructorBodyOperation : BaseMethodBodyBaseOperation, IConstructorBodyOperation - { - protected BaseConstructorBodyOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax) : - base(OperationKind.ConstructorBody, semanticModel, syntax) - { - Locals = locals; - } - - public ImmutableArray Locals { get; } - public abstract IOperation Initializer { get; } - - public sealed override IEnumerable Children - { - get - { - IOperation initializer = Initializer; - if (initializer != null) - { - yield return initializer; - } - - IBlockOperation blockBody = BlockBody; - if (blockBody != null) - { - yield return blockBody; - } - - IBlockOperation expressionBody = ExpressionBody; - if (expressionBody != null) - { - yield return expressionBody; - } - } - } - - public sealed override void Accept(OperationVisitor visitor) - { - visitor.VisitConstructorBodyOperation(this); - } - - public sealed override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitConstructorBodyOperation(this, argument); - } - } - - internal sealed class ConstructorBodyOperation : BaseConstructorBodyOperation - { - public ConstructorBodyOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, - IOperation initializer, IBlockOperation blockBody, IBlockOperation expressionBody) : - base(locals, semanticModel, syntax) - { - Initializer = SetParentOperation(initializer, this); - BlockBody = SetParentOperation(blockBody, this); - ExpressionBody = SetParentOperation(expressionBody, this); - } - - public override IOperation Initializer { get; } - public override IBlockOperation BlockBody { get; } - public override IBlockOperation ExpressionBody { get; } - } - - internal abstract class LazyConstructorBodyOperation : BaseConstructorBodyOperation - { - private IOperation _lazyInitializerInterlocked = s_unset; - private IBlockOperation _lazyBlockBodyInterlocked = s_unsetBlock; - private IBlockOperation _lazyExpressionBodyInterlocked = s_unsetBlock; - - public LazyConstructorBodyOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax) : - base(locals, semanticModel, syntax) - { - } - - protected abstract IOperation CreateInitializer(); - protected abstract IBlockOperation CreateBlockBody(); - protected abstract IBlockOperation CreateExpressionBody(); - - public override IOperation Initializer - { - get - { - if (_lazyInitializerInterlocked == s_unset) - { - IOperation initializer = CreateInitializer(); - SetParentOperation(initializer, this); - Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unset); - } - - return _lazyInitializerInterlocked; - } - } - - public override IBlockOperation BlockBody - { - get - { - if (_lazyBlockBodyInterlocked == s_unsetBlock) - { - IBlockOperation blockBody = CreateBlockBody(); - SetParentOperation(blockBody, this); - Interlocked.CompareExchange(ref _lazyBlockBodyInterlocked, blockBody, s_unsetBlock); - } - - return _lazyBlockBodyInterlocked; - } - } - - public override IBlockOperation ExpressionBody - { - get - { - if (_lazyExpressionBodyInterlocked == s_unsetBlock) - { - IBlockOperation expressionBody = CreateExpressionBody(); - SetParentOperation(expressionBody, this); - Interlocked.CompareExchange(ref _lazyExpressionBodyInterlocked, expressionBody, s_unsetBlock); - } - - return _lazyExpressionBodyInterlocked; - } - } - } - - internal sealed partial class DiscardPatternOperation : BasePatternOperation, IDiscardPatternOperation - { - public DiscardPatternOperation(ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : - base(inputType, OperationKind.DiscardPattern, semanticModel, syntax, type: default, constantValue: default, isImplicit) - { - } - } - - /// - /// Represents a standalone VB query Aggregate operation with more than one item in Into clause. - /// - internal abstract partial class BaseAggregateQueryOperation : Operation, IAggregateQueryOperation - { - protected BaseAggregateQueryOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.None, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - public override IEnumerable Children - { - get - { - if (Group != null) - { - yield return Group; - } - if (Aggregation != null) - { - yield return Aggregation; - } - } - } - - /// - /// See BoundAggregateClause node in VB compiler. - /// - public abstract IOperation Group { get; } - - /// - /// See BoundAggregateClause node in VB compiler. - /// - public abstract IOperation Aggregation { get; } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitAggregateQuery(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitAggregateQuery(this, argument); - } + public DeclarationPatternOperation( + ITypeSymbol inputType, + ITypeSymbol matchedType, + ISymbol declaredSymbol, + bool matchesNull, + SemanticModel semanticModel, + SyntaxNode syntax, + bool isImplicit) + : this(matchedType, matchesNull, declaredSymbol, inputType, semanticModel, syntax, type: default, constantValue: default, isImplicit) + { } } - /// - /// Represents a standalone VB query Aggregate operation with more than one item in Into clause. - /// - internal sealed partial class AggregateQueryOperation : BaseAggregateQueryOperation + internal sealed partial class RecursivePatternOperation : BaseRecursivePatternOperation { - public AggregateQueryOperation(IOperation group, IOperation aggregation, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - Group = SetParentOperation(group, this); - Aggregation = SetParentOperation(aggregation, this); - } - - public override IOperation Group { get; } - public override IOperation Aggregation { get; } + public RecursivePatternOperation( + ITypeSymbol inputType, + ITypeSymbol matchedType, + ISymbol deconstructSymbol, + ImmutableArray deconstructionSubpatterns, + ImmutableArray propertySubpatterns, + ISymbol declaredSymbol, SemanticModel semanticModel, + SyntaxNode syntax, + bool isImplicit) : + this(matchedType, deconstructSymbol, deconstructionSubpatterns, propertySubpatterns, declaredSymbol, inputType, semanticModel, syntax, type: null, constantValue: default, isImplicit) + { } } - /// - /// Represents a standalone VB query Aggregate operation with more than one item in Into clause. - /// - internal abstract class LazyAggregateQueryOperation : BaseAggregateQueryOperation + internal sealed partial class PropertySubpatternOperation : BasePropertySubpatternOperation { - private IOperation _lazyGroupInterlocked = s_unset; - private IOperation _lazyAggregationInterlocked = s_unset; - - public LazyAggregateQueryOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation CreateGroup(); - protected abstract IOperation CreateAggregation(); - - public override IOperation Group - { - get - { - if (_lazyGroupInterlocked == s_unset) - { - IOperation group = CreateGroup(); - SetParentOperation(group, this); - Interlocked.CompareExchange(ref _lazyGroupInterlocked, group, s_unset); - } - - return _lazyGroupInterlocked; - } - } - - public override IOperation Aggregation - { - get - { - if (_lazyAggregationInterlocked == s_unset) - { - IOperation aggregation = CreateAggregation(); - SetParentOperation(aggregation, this); - Interlocked.CompareExchange(ref _lazyAggregationInterlocked, aggregation, s_unset); - } - - return _lazyAggregationInterlocked; - } - } + public PropertySubpatternOperation( + SemanticModel semanticModel, + SyntaxNode syntax, + bool isImplicit, + IOperation member, + IPatternOperation pattern) : + this(member, pattern, semanticModel, syntax, type: null, constantValue: default, isImplicit) + { } } - /// - /// Represents a creation of an instance of a NoPia interface, i.e. new I(), where I is an embedded NoPia interface. - /// - internal abstract partial class BaseNoPiaObjectCreationOperation : Operation, INoPiaObjectCreationOperation + internal abstract partial class BasePatternCaseClauseOperation : BaseCaseClauseOperation, IPatternCaseClauseOperation { - public BaseNoPiaObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.None, semanticModel, syntax, type, constantValue, isImplicit) + protected BasePatternCaseClauseOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(CaseKind.Pattern, label, OperationKind.CaseClause, semanticModel, syntax, type, constantValue, isImplicit) { } @@ -8952,330 +754,231 @@ public override IEnumerable Children { get { - if (Initializer != null) + if (Pattern != null) { - yield return Initializer; + yield return Pattern; + } + if (Guard != null) + { + yield return Guard; } } } - /// - /// Object or collection initializer, if any. - /// - public abstract IObjectOrCollectionInitializerOperation Initializer { get; } + public abstract IPatternOperation Pattern { get; } + public abstract IOperation Guard { get; } public override void Accept(OperationVisitor visitor) { - visitor.VisitNoPiaObjectCreation(this); + visitor.VisitPatternCaseClause(this); } public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitNoPiaObjectCreation(this, argument); + return visitor.VisitPatternCaseClause(this, argument); } } - /// - /// Represents a creation of an instance of a NoPia interface, i.e. new I(), where I is an embedded NoPia interface. - /// - internal sealed partial class NoPiaObjectCreationOperation : BaseNoPiaObjectCreationOperation + internal sealed partial class PatternCaseClauseOperation : BasePatternCaseClauseOperation, IPatternCaseClauseOperation { - public NoPiaObjectCreationOperation(IObjectOrCollectionInitializerOperation initializer, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public PatternCaseClauseOperation(ILabelSymbol label, IPatternOperation pattern, IOperation guardExpression, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(label, semanticModel, syntax, type, constantValue, isImplicit) { - Initializer = SetParentOperation(initializer, this); + Pattern = SetParentOperation(pattern, this); + Guard = SetParentOperation(guardExpression, this); } - public override IObjectOrCollectionInitializerOperation Initializer { get; } + + public override IPatternOperation Pattern { get; } + public override IOperation Guard { get; } } - /// - /// Represents a creation of an instance of a NoPia interface, i.e. new I(), where I is an embedded NoPia interface. - /// - internal abstract class LazyNoPiaObjectCreationOperation : BaseNoPiaObjectCreationOperation + internal abstract class LazyPatternCaseClauseOperation : BasePatternCaseClauseOperation, IPatternCaseClauseOperation { - private IObjectOrCollectionInitializerOperation _lazyInitializerInterlocked = s_unsetObjectOrCollectionInitializer; + private IPatternOperation _lazyPatternInterlocked = s_unsetPattern; + private IOperation _lazyGuardExpressionInterlocked = s_unset; - public LazyNoPiaObjectCreationOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public LazyPatternCaseClauseOperation(ILabelSymbol label, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(label, semanticModel, syntax, type, constantValue, isImplicit) { } - protected abstract IObjectOrCollectionInitializerOperation CreateInitializer(); + protected abstract IPatternOperation CreatePattern(); + protected abstract IOperation CreateGuard(); - public override IObjectOrCollectionInitializerOperation Initializer + public override IPatternOperation Pattern { get { - if (_lazyInitializerInterlocked == s_unsetObjectOrCollectionInitializer) + if (_lazyPatternInterlocked == s_unsetPattern) { - IObjectOrCollectionInitializerOperation initializer = CreateInitializer(); - SetParentOperation(initializer, this); - Interlocked.CompareExchange(ref _lazyInitializerInterlocked, initializer, s_unsetObjectOrCollectionInitializer); + IPatternOperation pattern = CreatePattern(); + SetParentOperation(pattern, this); + Interlocked.CompareExchange(ref _lazyPatternInterlocked, pattern, s_unsetPattern); } - return _lazyInitializerInterlocked; + return _lazyPatternInterlocked; } } - } - - internal abstract class BaseRangeOperation : Operation, IRangeOperation - { - protected BaseRangeOperation(bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IMethodSymbol symbol, bool isImplicit) : - base(OperationKind.Range, semanticModel, syntax, type, constantValue: default, isImplicit: isImplicit) - { - IsLifted = isLifted; - Method = symbol; - } - - public abstract IOperation LeftOperand { get; } - public abstract IOperation RightOperand { get; } - public bool IsLifted { get; } - public IMethodSymbol Method { get; } - public sealed override IEnumerable Children + public override IOperation Guard { get { - IOperation leftOperand = LeftOperand; - if (leftOperand != null) + if (_lazyGuardExpressionInterlocked == s_unset) { - yield return leftOperand; + IOperation guard = CreateGuard(); + SetParentOperation(guard, this); + Interlocked.CompareExchange(ref _lazyGuardExpressionInterlocked, guard, s_unset); } - IOperation rightOperand = RightOperand; - if (rightOperand != null) - { - yield return rightOperand; - } + return _lazyGuardExpressionInterlocked; } } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitRangeOperation(this); - } - - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitRangeOperation(this, argument); - } } - internal sealed class RangeOperation : BaseRangeOperation + internal sealed partial class SwitchExpressionOperation : BaseSwitchExpressionOperation { - public RangeOperation(bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IOperation leftOperand, IOperation rightOperand, IMethodSymbol symbol, bool isImplicit) : - base(isLifted, semanticModel, syntax, type, symbol, isImplicit) - { - LeftOperand = Operation.SetParentOperation(leftOperand, this); - RightOperand = Operation.SetParentOperation(rightOperand, this); - } - - public override IOperation LeftOperand { get; } - public override IOperation RightOperand { get; } + public SwitchExpressionOperation( + ITypeSymbol type, + IOperation value, + ImmutableArray arms, + SemanticModel semanticModel, + SyntaxNode syntax, + bool isImplicit) : + this(value, arms, semanticModel, syntax, type, constantValue: default, isImplicit) + { } } - internal abstract class LazyRangeOperation : BaseRangeOperation + internal sealed partial class SwitchExpressionArmOperation : BaseSwitchExpressionArmOperation { - private IOperation _leftOperandInterlocked = s_unset; - private IOperation _rightOperandInterlocked = s_unset; - - public LazyRangeOperation(bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IMethodSymbol symbol, bool isImplicit) : - base(isLifted, semanticModel, syntax, type, symbol, isImplicit) - { - } - - protected abstract IOperation CreateLeftOperand(); - protected abstract IOperation CreateRightOperand(); + public SwitchExpressionArmOperation( + ImmutableArray locals, + IPatternOperation pattern, + IOperation guard, + IOperation value, + SemanticModel semanticModel, + SyntaxNode syntax, + bool isImplicit) : + this(pattern, guard, value, locals, semanticModel, syntax, type: null, constantValue: default, isImplicit) + { } + } - public override IOperation LeftOperand + internal sealed partial class FlowCaptureReferenceOperation : Operation, IFlowCaptureReferenceOperation + { + public FlowCaptureReferenceOperation(int id, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(OperationKind.FlowCaptureReference, semanticModel: null, syntax: syntax, type: type, constantValue: constantValue, isImplicit: true) { - get - { - if (_leftOperandInterlocked == s_unset) - { - IOperation leftOperand = CreateLeftOperand(); - SetParentOperation(leftOperand, this); - Interlocked.CompareExchange(ref _leftOperandInterlocked, leftOperand, s_unset); - } - - return _leftOperandInterlocked; - } + Id = new CaptureId(id); } - public override IOperation RightOperand + public FlowCaptureReferenceOperation(CaptureId id, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(OperationKind.FlowCaptureReference, semanticModel: null, syntax: syntax, type: type, constantValue: constantValue, isImplicit: true) { - get - { - if (_rightOperandInterlocked == s_unset) - { - IOperation rightOperand = CreateRightOperand(); - SetParentOperation(rightOperand, this); - Interlocked.CompareExchange(ref _rightOperandInterlocked, rightOperand, s_unset); - } - - return _rightOperandInterlocked; - } + Id = id; } } - internal abstract class BaseReDimOperation : Operation, IReDimOperation + internal sealed partial class FlowCaptureOperation : Operation, IFlowCaptureOperation { - protected BaseReDimOperation(bool preserve, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.ReDim, semanticModel, syntax, type, constantValue, isImplicit) + public FlowCaptureOperation(int id, SyntaxNode syntax, IOperation value) : + base(OperationKind.FlowCapture, semanticModel: null, syntax: syntax, type: null, constantValue: default, isImplicit: true) { - Preserve = preserve; + Debug.Assert(value != null); + Id = new CaptureId(id); + Value = SetParentOperation(value, this); } - public abstract ImmutableArray Clauses { get; } - public bool Preserve { get; } - - public sealed override IEnumerable Children + public CaptureId Id { get; } + public IOperation Value { get; } + public override IEnumerable Children { get { - foreach (var clause in Clauses) - { - yield return clause; - } + yield return Value; } } - public sealed override void Accept(OperationVisitor visitor) - { - visitor.VisitReDim(this); - } - - public sealed override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitReDim(this, argument); - } - } - - internal sealed class ReDimOperation : BaseReDimOperation - { - public ReDimOperation(ImmutableArray clauses, bool preserve, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(preserve, semanticModel, syntax, type, constantValue, isImplicit) - { - Clauses = SetParentOperation(clauses, this); - } - - public override ImmutableArray Clauses { get; } - } - - internal abstract class LazyReDimOperation : BaseReDimOperation - { - private ImmutableArray _lazyClausesInterlocked; - - public LazyReDimOperation(bool preserve, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(preserve, semanticModel, syntax, type, constantValue, isImplicit) + public override void Accept(OperationVisitor visitor) { + visitor.VisitFlowCapture(this); } - protected abstract ImmutableArray CreateClauses(); - - public override ImmutableArray Clauses + public override TResult Accept(OperationVisitor visitor, TArgument argument) { - get - { - if (_lazyClausesInterlocked.IsDefault) - { - ImmutableArray clauses = CreateClauses(); - SetParentOperation(clauses, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyClausesInterlocked, clauses, default); - } - - return _lazyClausesInterlocked; - } + return visitor.VisitFlowCapture(this, argument); } } - internal abstract class BaseReDimClauseOperation : Operation, IReDimClauseOperation + internal sealed partial class IsNullOperation : Operation, IIsNullOperation { - protected BaseReDimClauseOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.ReDimClause, semanticModel, syntax, type, constantValue, isImplicit) + public IsNullOperation(SyntaxNode syntax, IOperation operand, ITypeSymbol type, Optional constantValue) : + base(OperationKind.IsNull, semanticModel: null, syntax: syntax, type: type, constantValue: constantValue, isImplicit: true) { + Debug.Assert(operand != null); + Operand = SetParentOperation(operand, this); } - public abstract IOperation Operand { get; } - public abstract ImmutableArray DimensionSizes { get; } - - public sealed override IEnumerable Children + public IOperation Operand { get; } + public override IEnumerable Children { get { - Debug.Assert(Operand != null); yield return Operand; - - foreach (var index in DimensionSizes) - { - Debug.Assert(index != null); - yield return index; - } } } - public sealed override void Accept(OperationVisitor visitor) + public override void Accept(OperationVisitor visitor) { - visitor.VisitReDimClause(this); + visitor.VisitIsNull(this); } - public sealed override TResult Accept(OperationVisitor visitor, TArgument argument) + public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitReDimClause(this, argument); + return visitor.VisitIsNull(this, argument); } } - internal sealed class ReDimClauseOperation : BaseReDimClauseOperation + internal sealed partial class CaughtExceptionOperation : Operation, ICaughtExceptionOperation { - public ReDimClauseOperation(IOperation operand, ImmutableArray dimensionSizes, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public CaughtExceptionOperation(SyntaxNode syntax, ITypeSymbol type) : + this(semanticModel: null, syntax: syntax, type: type, constantValue: default, isImplicit: true) { - Operand = SetParentOperation(operand, this); - DimensionSizes = SetParentOperation(dimensionSizes, this); } - - public override IOperation Operand { get; } - public override ImmutableArray DimensionSizes { get; } } - internal abstract class LazyReDimClauseOperation : BaseReDimClauseOperation + internal sealed partial class StaticLocalInitializationSemaphoreOperation : Operation, IStaticLocalInitializationSemaphoreOperation { - private IOperation _lazyOperandInterlocked = s_unset; - private ImmutableArray _lazyDimensionSizesInterlocked; - - public LazyReDimClauseOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public StaticLocalInitializationSemaphoreOperation(ILocalSymbol local, SyntaxNode syntax, ITypeSymbol type) : + base(OperationKind.StaticLocalInitializationSemaphore, semanticModel: null, syntax, type, constantValue: default, isImplicit: true) { + Local = local; } + } - protected abstract IOperation CreateOperand(); - protected abstract ImmutableArray CreateDimensionSizes(); + internal sealed partial class MethodBodyOperation : BaseMethodBodyOperation + { + public MethodBodyOperation(SemanticModel semanticModel, SyntaxNode syntax, IBlockOperation blockBody, IBlockOperation expressionBody) : + this(blockBody, expressionBody, semanticModel, syntax, type: null, constantValue: default, isImplicit: false) + { } + } - public override IOperation Operand - { - get - { - if (_lazyOperandInterlocked == s_unset) - { - IOperation operand = CreateOperand(); - SetParentOperation(operand, this); - Interlocked.CompareExchange(ref _lazyOperandInterlocked, operand, s_unset); - } + internal sealed partial class ConstructorBodyOperation : BaseConstructorBodyOperation + { + public ConstructorBodyOperation(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, + IOperation initializer, IBlockOperation blockBody, IBlockOperation expressionBody) : + this(locals, initializer, blockBody, expressionBody, semanticModel, syntax, type: null, constantValue: default, isImplicit: false) + { } + } - return _lazyOperandInterlocked; - } - } + internal sealed partial class DiscardPatternOperation : BasePatternOperation, IDiscardPatternOperation + { + public DiscardPatternOperation(ITypeSymbol inputType, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) : + this(inputType, semanticModel, syntax, type: null, constantValue: default, isImplicit) + { } - public override ImmutableArray DimensionSizes - { - get - { - if (_lazyDimensionSizesInterlocked.IsDefault) - { - ImmutableArray dimensionSizes = CreateDimensionSizes(); - SetParentOperation(dimensionSizes, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDimensionSizesInterlocked, dimensionSizes, default); - } + } - return _lazyDimensionSizesInterlocked; - } - } + internal sealed partial class RangeOperation : BaseRangeOperation + { + public RangeOperation(bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IOperation leftOperand, IOperation rightOperand, IMethodSymbol symbol, bool isImplicit) : + this(leftOperand, rightOperand, isLifted, method: symbol, semanticModel, syntax, type, constantValue: default, isImplicit) + { } } } diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index 8029cd6962f2b..6f4b97248e475 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -1581,7 +1581,7 @@ Namespace Microsoft.CodeAnalysis.Operations Dim type As ITypeSymbol = boundAnonymousTypePropertyAccess.Type Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundAnonymousTypePropertyAccess.ConstantValueOpt) Dim isImplicit As Boolean = boundAnonymousTypePropertyAccess.WasCompilerGenerated - Return New PropertyReferenceOperation([property], instance, arguments, _semanticModel, syntax, type, constantValue, isImplicit) + Return New PropertyReferenceOperation([property], arguments, instance, _semanticModel, syntax, type, constantValue, isImplicit) End Function Private Function CreateAnonymousTypePropertyAccessImplicitReceiverOperation(propertySym As IPropertySymbol, syntax As SyntaxNode) As InstanceReferenceOperation diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory_Methods.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory_Methods.vb index e07f3f94c27c6..a78723ff04347 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory_Methods.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory_Methods.vb @@ -351,8 +351,8 @@ Namespace Microsoft.CodeAnalysis.Operations Dim instance As IInstanceReferenceOperation = CreateAnonymousTypePropertyAccessImplicitReceiverOperation([property], expression.Syntax) target = New PropertyReferenceOperation( [property], - instance, ImmutableArray(Of IArgumentOperation).Empty, + instance, _semanticModel, value.Syntax, [property].Type, @@ -370,7 +370,7 @@ Namespace Microsoft.CodeAnalysis.Operations Dim syntax As SyntaxNode = If(value.Syntax?.Parent, expression.Syntax) Dim type As ITypeSymbol = target.Type Dim constantValue As [Optional](Of Object) = value.ConstantValue - Dim assignment = New SimpleAssignmentOperation(target, isRef, value, _semanticModel, syntax, type, constantValue, isImplicitAssignment) + Dim assignment = New SimpleAssignmentOperation(isRef, target, value, _semanticModel, syntax, type, constantValue, isImplicitAssignment) builder.Add(assignment) Next i diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationNodes.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationNodes.vb index 265222312a856..fbd48aaf12ea0 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationNodes.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationNodes.vb @@ -122,7 +122,7 @@ Namespace Microsoft.CodeAnalysis.Operations Private ReadOnly _arrayInitialization As BoundArrayInitialization Friend Sub New(operationFactory As VisualBasicOperationFactory, arrayInitialization As BoundArrayInitialization, semanticModel As SemanticModel, syntax As SyntaxNode, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(semanticModel, syntax, constantValue, isImplicit) + MyBase.New(semanticModel, syntax, type:=Nothing, constantValue, isImplicit) _operationFactory = operationFactory _arrayInitialization = arrayInitialization End Sub @@ -362,7 +362,7 @@ Namespace Microsoft.CodeAnalysis.Operations Private ReadOnly _value As BoundNode Friend Sub New(operationFactory As VisualBasicOperationFactory, value As BoundNode, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(locals:=ImmutableArray(Of ILocalSymbol).Empty, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _value = value End Sub @@ -379,7 +379,7 @@ Namespace Microsoft.CodeAnalysis.Operations Private ReadOnly _value As BoundNode Friend Sub New(operationFactory As VisualBasicOperationFactory, value As BoundNode, locals As ImmutableArray(Of ILocalSymbol), initializedFields As ImmutableArray(Of IFieldSymbol), kind As OperationKind, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(locals, initializedFields, kind, semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(initializedFields, locals, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _value = value End Sub @@ -413,7 +413,7 @@ Namespace Microsoft.CodeAnalysis.Operations Private ReadOnly _forEachLoop As BoundForEachStatement Friend Sub New(operationFactory As VisualBasicOperationFactory, forEachLoop As BoundForEachStatement, locals As ImmutableArray(Of ILocalSymbol), continueLabel As ILabelSymbol, exitLabel As ILabelSymbol, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(LoopKind.ForEach, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _forEachLoop = forEachLoop End Sub @@ -446,7 +446,7 @@ Namespace Microsoft.CodeAnalysis.Operations Private ReadOnly _boundForToLoop As BoundForToStatement Friend Sub New(operationFactory As VisualBasicOperationFactory, boundForToLoop As BoundForToStatement, locals As ImmutableArray(Of ILocalSymbol), isChecked As Boolean, info As (LoopObject As ILocalSymbol, UserDefinedInfo As ForToLoopOperationUserDefinedInfo), continueLabel As ILabelSymbol, exitLabel As ILabelSymbol, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(locals, isChecked, info, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(isChecked, info, LoopKind.ForTo, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _boundForToLoop = boundForToLoop End Sub @@ -806,7 +806,7 @@ _operationFactory.CreateFromArray(Of BoundExpression, IOperation)(_boundForToLoo Private ReadOnly _value As BoundNode Friend Sub New(operationFactory As VisualBasicOperationFactory, value As BoundNode, locals As ImmutableArray(Of ILocalSymbol), parameter As IParameterSymbol, kind As OperationKind, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(locals, parameter, kind, semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(parameter, locals, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _value = value End Sub @@ -840,7 +840,7 @@ _operationFactory.CreateFromArray(Of BoundExpression, IOperation)(_boundForToLoo Private ReadOnly _value As BoundNode Friend Sub New(operationFactory As VisualBasicOperationFactory, value As BoundNode, locals As ImmutableArray(Of ILocalSymbol), initializedProperties As ImmutableArray(Of IPropertySymbol), kind As OperationKind, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(locals, initializedProperties, kind, semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(initializedProperties, locals, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _value = value End Sub @@ -880,7 +880,7 @@ _operationFactory.CreateFromArray(Of BoundExpression, IOperation)(_boundForToLoo Private ReadOnly _rangeCaseClause As BoundRangeCaseClause Friend Sub New(operationFactory As VisualBasicOperationFactory, rangeCaseClause As BoundRangeCaseClause, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(CaseKind.Range, label:=Nothing, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _rangeCaseClause = rangeCaseClause End Sub @@ -901,7 +901,7 @@ _operationFactory.CreateFromArray(Of BoundExpression, IOperation)(_boundForToLoo Private ReadOnly _value As BoundNode Friend Sub New(operationFactory As VisualBasicOperationFactory, value As BoundNode, relation As BinaryOperatorKind, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(relation, semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(relation, CaseKind.Relational, label:=Nothing, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _value = value End Sub @@ -935,7 +935,7 @@ _operationFactory.CreateFromArray(Of BoundExpression, IOperation)(_boundForToLoo Private ReadOnly _value As BoundNode Friend Sub New(operationFactory As VisualBasicOperationFactory, value As BoundNode, label As ILabelSymbol, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(label, semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(CaseKind.SingleValue, label, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _value = value End Sub @@ -1023,7 +1023,7 @@ _operationFactory.CreateFromArray(Of BoundExpression, IOperation)(_boundForToLoo Private ReadOnly _tupleExpression As BoundTupleExpression Friend Sub New(operationFactory As VisualBasicOperationFactory, tupleExpression As BoundTupleExpression, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, naturalType As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(semanticModel, syntax, type, naturalType, constantValue, isImplicit) + MyBase.New(naturalType, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _tupleExpression = tupleExpression End Sub @@ -1133,7 +1133,7 @@ _operationFactory.CreateFromArray(Of BoundExpression, IOperation)(_boundForToLoo Private ReadOnly _conditionalLoop As IBoundConditionalLoop Friend Sub New(operationFactory As VisualBasicOperationFactory, conditionalLoop As IBoundConditionalLoop, locals As ImmutableArray(Of ILocalSymbol), continueLabel As ILabelSymbol, exitLabel As ILabelSymbol, conditionIsTop As Boolean, conditionIsUntil As Boolean, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean) - MyBase.New(locals, continueLabel, exitLabel, conditionIsTop, conditionIsUntil, semanticModel, syntax, type, constantValue, isImplicit) + MyBase.New(conditionIsTop, conditionIsUntil, LoopKind.While, locals, continueLabel, exitLabel, semanticModel, syntax, type, constantValue, isImplicit) _operationFactory = operationFactory _conditionalLoop = conditionalLoop End Sub diff --git a/src/Compilers/VisualBasic/Portable/VisualBasicExtensions.vb b/src/Compilers/VisualBasic/Portable/VisualBasicExtensions.vb index 3dd3e271c6e32..629342c93047f 100644 --- a/src/Compilers/VisualBasic/Portable/VisualBasicExtensions.vb +++ b/src/Compilers/VisualBasic/Portable/VisualBasicExtensions.vb @@ -1374,7 +1374,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public Function GetConversion(conversionExpression As IConversionOperation) As Conversion If conversionExpression.Language = LanguageNames.VisualBasic Then - Return DirectCast(DirectCast(conversionExpression, BaseConversionOperation).ConvertibleConversion, Conversion) + Return DirectCast(DirectCast(conversionExpression, BaseConversionOperation).ConversionConvertible, Conversion) Else Throw New ArgumentException(String.Format(VBResources.IConversionExpressionIsNotVisualBasicConversion, NameOf(IConversionOperation)), diff --git a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs index 55a705b6b4824..9d87867c3c07f 100644 --- a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs +++ b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs @@ -1137,7 +1137,7 @@ public override void VisitConversion(IConversionOperation operation) { LogNewLine(); Indent(); - LogString($"({((BaseConversionOperation)operation).ConvertibleConversion})"); + LogString($"({((BaseConversionOperation)operation).ConversionConvertible})"); Unindent(); } @@ -1173,7 +1173,7 @@ public override void VisitCoalesce(ICoalesceOperation operation) LogConversion(operation.ValueConversion, "ValueConversion"); LogNewLine(); Indent(); - LogString($"({((BaseCoalesceOperation)operation).ConvertibleValueConversion})"); + LogString($"({((BaseCoalesceOperation)operation).ValueConversionConvertible})"); Unindent(); LogNewLine(); Unindent(); diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs new file mode 100644 index 0000000000000..8814c50e16622 --- /dev/null +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs @@ -0,0 +1,84 @@ +using System; +using System.Linq; + +namespace IOperationGenerator +{ + internal sealed partial class IOperationClassWriter + { + private bool ModelHasErrors(Tree tree) + { + bool error = false; + + foreach (var abstractNode in tree.Types.OfType()) + { + if (!abstractNode.Name.StartsWith("I")) + { + Console.WriteLine($"All IOperation node names must start with I. {abstractNode.Name} does not."); + error = true; + } + + if (!abstractNode.Name.EndsWith("Operation")) + { + Console.WriteLine($"All IOperation node names must end with Operation. {abstractNode.Name} does not."); + } + + if (!_typeMap.ContainsKey(abstractNode.Base)) + { + Console.WriteLine($"{abstractNode.Name}'s base type is not an IOperation type."); + error = true; + } + + if (!abstractNode.IsInternal && abstractNode.Obsolete is null) + { + if (abstractNode.Comments?.Elements?[0].Name != "summary") + { + Console.WriteLine($"{abstractNode.Name} does not have correctly formatted comments, please ensure that there is a block for the type."); + error = true; + } + + foreach (var prop in abstractNode.Properties) + { + if (prop.Comments?.Elements?[0].Name != "summary" && !prop.IsInternal) + { + Console.WriteLine($"{abstractNode.Name}.{prop.Name} does not have correctly formatted comments, please ensure that there is a block for the type."); + error = true; + } + } + } + + if (!(abstractNode is Node node)) continue; + + var properties = GetAllGeneratedIOperationProperties(node).Where(p => !p.IsInternal).Select(p => p.Name).ToList(); + + if (properties.Count < 2) continue; + if (node.SkipChildrenGeneration || node.SkipClassGeneration) continue; + + if (node.ChildrenOrder is null) + { + Console.WriteLine($"{node.Name} has more than 1 IOperation properties and must declare an explicit ordering with the ChildrenOrder attribute."); + Console.WriteLine($"Properties: {string.Join(", ", properties)}"); + error = true; + continue; + } + + var childrenOrdered = node.ChildrenOrder.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList(); + foreach (var child in childrenOrdered) + { + if (!properties.Remove(child)) + { + Console.WriteLine($"{node.Name}'s ChildrenOrder contains unknown property {child}"); + error = true; + } + } + + foreach (var remainingProp in properties) + { + Console.WriteLine($"{node.Name}'s ChildrenOrder is missing {remainingProp}"); + error = true; + } + } + + return error; + } + } +} diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index 01cdd9a3aa70b..c6620895e1a53 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -18,7 +18,7 @@ internal enum NullHandling NotApplicable // for value types } - internal sealed class IOperationClassWriter + internal sealed partial class IOperationClassWriter { private TextWriter _writer = null!; private readonly string _location; @@ -90,6 +90,12 @@ private void Outdent() private void WriteFiles() { + if (ModelHasErrors(_tree)) + { + Console.WriteLine("Encountered xml errors, not generating"); + return; + } + foreach (var grouping in _tree.Types.OfType().GroupBy(n => n.Namespace)) { var @namespace = grouping.Key ?? "Operations"; @@ -102,6 +108,7 @@ private void WriteFiles() if (@namespace == "Operations") { WriteUsing("System.Collections.Generic"); + WriteUsing("System.Threading"); } WriteUsing("System.Collections.Immutable"); @@ -239,6 +246,7 @@ void writeReservedRemarkText() private void WriteInterfaceProperty(Property prop) { + if (prop.IsInternal) return; WriteComments(prop.Comments, writeReservedRemark: false); var modifiers = prop.IsNew ? "new " : ""; WriteLine($"{modifiers}{prop.Type} {prop.Name} {{ get; }}"); @@ -340,80 +348,202 @@ private void WriteClasses() if (type.SkipClassGeneration) continue; var allProps = GetAllProperties(type); + bool hasSkippedProperties = !GetAllProperties(type, includeSkipGenerationProperties: true).SequenceEqual(allProps); var ioperationTypes = allProps.Where(p => IsIOperationType(p.Type)).ToList(); - if (ioperationTypes.Count == 0) + var publicIOperationTypes = ioperationTypes.Where(p => !p.IsInternal).ToList(); + var hasIOpChildren = ioperationTypes.Count != 0; + var constructorAccessibility = type.IsAbstract ? "protected" : "internal"; + string typeName = type.Name[1..]; + + IEnumerable? baseProperties = null; + if (_typeMap[type.Base] is { } baseNode) + { + baseProperties = GetAllProperties(baseNode); + } + + + // Start by generating any necessary base classes + if (hasIOpChildren || type.IsAbstract) { - // No children, no need for lazy generation - var @class = (type.IsAbstract ? "Base" : "") + type.Name.Substring(1); - var extensibility = type.IsAbstract ? "abstract" : "sealed"; - var baseType = type.Base.Substring(1); + var @class = $"Base{typeName}"; + var baseType = type.Base[1..]; if (baseType != "Operation") { baseType = $"Base{baseType}"; } - WriteLine($"internal {extensibility} partial class {@class} : {baseType}, {type.Name}"); - Brace(); + writeClassHeader("abstract", @class, baseType, type.Name); - var accessibility = type.IsAbstract ? "protected" : "internal"; - Write($"{accessibility} {@class}("); + writeConstructor(constructorAccessibility, @class, allProps, baseProperties, type, ClassType.Abstract); - foreach (var prop in allProps) + foreach (var prop in type.Properties) { - Debug.Assert(!IsIOperationType(prop.Type)); - Write($"{prop.Type} {prop.Name.ToCamelCase()}, "); + if (prop.SkipGeneration) continue; + writeProperty(prop, propExtensibility: IsIOperationType(prop.Type) ? "abstract " : string.Empty); } - writeStandardConstructorParameters(type.IsAbstract); - Indent(); - Write(": base("); - - var @base = _typeMap[type.Base]; - if (@base is object) + if (type is Node node) { - foreach (var prop in GetAllProperties(@base).Where(p => !IsIOperationType(p.Type))) + if (!node.SkipChildrenGeneration) { - Write($"{prop.Name.ToCamelCase()}, "); + if (publicIOperationTypes.Count > 0) + { + var orderedProperties = new List(); + + if (publicIOperationTypes.Count == 1) + { + orderedProperties.Add(publicIOperationTypes.Single()); + } + else + { + Debug.Assert(node.ChildrenOrder != null, $"Encountered null children order for {type.Name}, should have been caught in verifier!"); + var childrenOrdered = node.ChildrenOrder.Split(",", StringSplitOptions.RemoveEmptyEntries); + + foreach (var childName in childrenOrdered) + { + orderedProperties.Add(publicIOperationTypes.Find(p => p.Name == childName) ?? + throw new InvalidOperationException($"Cannot find property for {childName}")); + } + } + + WriteLine("public override IEnumerable Children"); + Brace(); + WriteLine("get"); + Brace(); + + foreach (var property in orderedProperties) + { + if (IsImmutableArray(property.Type, out _)) + { + WriteLine($"foreach (var child in {property.Name})"); + Brace(); + writeIfCheck("child"); + Unbrace(); + } + else + { + writeIfCheck(property.Name); + } + + void writeIfCheck(string memberName) + { + WriteLine($"if ({memberName} is object) yield return {memberName};"); + } + } + Unbrace(); + Unbrace(); + } + else + { + WriteLine("public override IEnumerable Children => Array.Empty();"); + } } + + var visitorName = GetVisitorName(node); + writeAcceptMethods(visitorName); } - writeStandardBaseArguments(type switch + Unbrace(); + } + + if (type.IsAbstract) continue; + + // Generate the non-lazy class. Nested block to allow for duplicate variable names + { + var @class = typeName; + var @base = hasIOpChildren ? @class : type.Base[1..]; + if (@base != "Operation") { - { IsAbstract: true } => "kind", - { IsInternal: true } => "OperationKind.None", - _ => $"OperationKind.{getKind(type)}" - }); - Outdent(); - // The base class is responsible for initializing its own properties, - // so we only initialize our own properties here. - if (type.Properties.Count == 0) + @base = $"Base{@base}"; + } + + writeClassHeader("sealed", @class, @base, type.Name); + writeConstructor( + constructorAccessibility, + @class, + allProps, + hasIOpChildren ? allProps : baseProperties, + type, + ClassType.NonLazy, + includeKind: !hasIOpChildren); + + if (hasIOpChildren) { - // Note: our formatting style is a space here - WriteLine(" { }"); + foreach (var property in ioperationTypes) + { + writeProperty(property, propExtensibility: "override "); + } } else { - Blank(); - Brace(); - foreach (var prop in type.Properties) + foreach (var property in type.Properties) { - WriteLine($"{prop.Name} = {prop.Name.ToCamelCase()};"); + if (property.SkipGeneration) continue; + writeProperty(property, propExtensibility: string.Empty); } - Unbrace(); + + var node = (Node)type; + WriteLine("public override IEnumerable Children => Array.Empty();"); + writeAcceptMethods(GetVisitorName(node)); } + Unbrace(); + } - foreach (var prop in type.Properties) + // Generate the lazy classes if necessary + if (hasIOpChildren) + { + var @class = $"Lazy{typeName}"; + var @base = $"Base{typeName}"; + + writeClassHeader("abstract", @class, @base, type.Name); + + var propertiesAndFieldNames = ioperationTypes.Select(i => (i, $"_lazy{i.Name}", $"s_unset{GetSubName(i.Type)}")).ToList(); + + foreach (var (prop, name, unset) in propertiesAndFieldNames) { - WriteLine($"public {prop.Type} {prop.Name} {{ get; }}"); + var assignment = string.Empty; + if (!IsImmutableArray(prop.Type, out _)) + { + assignment = $" = {unset}"; + } + + WriteLine($"private {prop.Type} {name}{assignment};"); } - if (type is Node node) + writeConstructor(constructorAccessibility, @class, allProps, allProps, type, ClassType.Lazy, includeKind: false); + + foreach (var (prop, fieldName, unset) in propertiesAndFieldNames) { + WriteLine($"protected abstract {prop.Type} Create{prop.Name}();"); + WriteLine($"public override {prop.Type} {prop.Name}"); + Brace(); + WriteLine("get"); + Brace(); + if (IsImmutableArray(prop.Type, out _)) + { + WriteLine($"if ({fieldName}.IsDefault)"); + Brace(); + var localName = prop.Name.ToCamelCase(); + WriteLine($"{prop.Type} {localName} = Create{prop.Name}();"); + WriteLine($"SetParentOperation({localName}, this);"); + WriteLine($"ImmutableInterlocked.InterlockedCompareExchange(ref {fieldName}, {localName}, default);"); + Unbrace(); - var visitorName = GetVisitorName(node); - WriteLine($@"public override IEnumerable Children => Array.Empty(); - public override void Accept(OperationVisitor visitor) => visitor.{visitorName}(this); - public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.{visitorName}(this, argument);"); + } + else + { + WriteLine($"if ({fieldName} == {unset})"); + Brace(); + var localName = prop.Name.ToCamelCase(); + WriteLine($"{prop.Type} {localName} = Create{prop.Name}();"); + WriteLine($"SetParentOperation({localName}, this);"); + WriteLine($"Interlocked.CompareExchange(ref {fieldName}, {localName}, {unset});"); + Unbrace(); + } + + WriteLine($"return {fieldName};"); + Unbrace(); + Unbrace(); } Unbrace(); @@ -422,19 +552,133 @@ private void WriteClasses() WriteLine("#endregion"); - void writeStandardConstructorParameters(bool isAbstract) + void writeClassHeader(string extensibility, string @class, string baseType, string @interface) { - if (isAbstract) + WriteLine($"internal {extensibility} partial class {@class} : {baseType}, {@interface}"); + Brace(); + } + + void writeConstructor(string accessibility, string @class, IEnumerable properties, IEnumerable? baseProperties, AbstractNode type, ClassType classType, bool includeKind = true) + { + Write($"{accessibility} {@class}("); + foreach (var prop in properties) + { + if (classType != ClassType.NonLazy && IsIOperationType(prop.Type)) continue; + if (prop.Type == "CommonConversion") + { + Write($"IConvertibleConversion {prop.Name.ToCamelCase()}, "); + } + else + { + Write($"{prop.Type} {prop.Name.ToCamelCase()}, "); + } + } + + var multipleValidKinds = (type.OperationKind?.Entries?.Where(e => e.EditorBrowsable != false).Count() ?? 0) > 1; + if (type.IsAbstract || multipleValidKinds) { Write("OperationKind kind, "); } + Write("SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit"); + + WriteLine(")"); + Indent(); + Write(": base("); + + var @base = _typeMap[type.Base]; + if (baseProperties is object) + { + foreach (var prop in baseProperties.Where(p => !IsIOperationType(p.Type))) + { + Write($"{prop.Name.ToCamelCase()}, "); + } + } + + var kind = type switch + { + { IsAbstract: true } => "kind", + { } when multipleValidKinds => "kind", + { IsInternal: true } => "OperationKind.None", + _ => $"OperationKind.{getKind(type)}" + }; + Write($"{(includeKind || multipleValidKinds ? $"{kind}, " : string.Empty)}semanticModel, syntax, type, constantValue, isImplicit)"); + + Outdent(); + + // Lazy constructors never initialize anything + if (classType == ClassType.Lazy) + { + WriteLine("{ }"); + return; + } + + // For leaf types, we need to initialize all IOperations from any parent classes, and our own. If this class has no IOperation + // children, then that means there's no lazy version of the class, and we need to initialize all the properties defined on this + // interface instead. + var propsAreIOperations = true; + List propsToInitialize; + if (classType == ClassType.NonLazy) + { + propsToInitialize = GetAllGeneratedIOperationProperties(type); + if (propsToInitialize.Count == 0) + { + propsToInitialize = type.Properties.Where(p => !p.SkipGeneration).ToList(); + propsAreIOperations = false; + } + } + else + { + propsToInitialize = type.Properties.Where(p => !IsIOperationType(p.Type) && !p.SkipGeneration).ToList(); + propsAreIOperations = false; + } + + if (propsToInitialize.Count == 0) + { + // Note: our formatting style is a space here + WriteLine(" { }"); + } + else + { + Blank(); + Brace(); + foreach (var prop in propsToInitialize) + { + if (prop.Type == "CommonConversion") + { + WriteLine($"{prop.Name}Convertible = {prop.Name.ToCamelCase()};"); + } + else + { + var initializer = propsAreIOperations ? + $"SetParentOperation({prop.Name.ToCamelCase()}, this)" : + prop.Name.ToCamelCase(); + WriteLine($"{prop.Name} = {initializer};"); + } + } + Unbrace(); + } + } - WriteLine("SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit)"); + void writeProperty(Property prop, string propExtensibility) + { + if (prop.Type == "CommonConversion") + { + // Common conversions need an internal property for the IConvertibleConversion + // version of the property, and the public version needs to call ToCommonConversion + WriteLine($"internal IConvertibleConversion {prop.Name}Convertible {{ get; }}"); + WriteLine($"public CommonConversion {prop.Name} => {prop.Name}Convertible.ToCommonConversion();"); + } + else + { + WriteLine($"public {propExtensibility}{prop.Type} {prop.Name} {{ get; }}"); + } } - void writeStandardBaseArguments(string kind) + void writeAcceptMethods(string visitorName) { - Write($"{kind}, semanticModel, syntax, type, constantValue, isImplicit)"); + WriteLine($"public override void Accept(OperationVisitor visitor) => visitor.{visitorName}(this);"); + WriteLine($"public override TResult Accept(OperationVisitor visitor, TArgument argument) => visitor.{visitorName}(this, argument);"); + } string getKind(AbstractNode node) @@ -507,13 +751,12 @@ private void WriteObsoleteIfNecessary(ObsoleteTag? tag) private string GetVisitorName(Node type) { - Debug.Assert(!type.SkipInVisitor, $"{type.Name} is marked as skipped in visitor, cannot generate classes."); return type.VisitorName ?? $"Visit{GetSubName(type.Name)}"; } - private List GetAllProperties(AbstractNode node) + private List GetAllProperties(AbstractNode node, bool includeSkipGenerationProperties = false) { - var properties = node.Properties.ToList(); + var properties = node.Properties.Where(p => !p.SkipGeneration || includeSkipGenerationProperties).ToList(); AbstractNode? @base = node; while (true) @@ -521,13 +764,18 @@ private List GetAllProperties(AbstractNode node) string baseName = @base.Base; @base = _typeMap[baseName]; if (@base is null) break; - properties.AddRange(@base.Properties); + properties.AddRange(@base.Properties.Where(p => !p.SkipGeneration || includeSkipGenerationProperties)); } return properties; } - private static string GetSubName(string operationName) => operationName[1..^9]; + private List GetAllGeneratedIOperationProperties(AbstractNode node) + { + return GetAllProperties(node).Where(p => IsIOperationType(p.Type)).ToList(); + } + + private string GetSubName(string operationName) => operationName[1..^9]; private bool IsIOperationType(string typeName) => _typeMap.ContainsKey(typeName) || (IsImmutableArray(typeName, out var innerType) && IsIOperationType(innerType)); @@ -544,10 +792,113 @@ private static bool IsImmutableArray(string typeName, [NotNullWhen(true)] out st arrayType = null; return false; } + + private enum ClassType + { + Abstract, + NonLazy, + Lazy + } } internal static class Extensions { - internal static string ToCamelCase(this string name) => char.ToLowerInvariant(name[0]) + name.Substring(1); + internal static string ToCamelCase(this string name) + { + var camelCased = char.ToLowerInvariant(name[0]) + name.Substring(1); + if (camelCased.IsCSharpKeyword()) + { + return "@" + camelCased; + } + + return camelCased; + } + + internal static bool IsCSharpKeyword(this string name) + { + switch (name) + { + case "bool": + case "byte": + case "sbyte": + case "short": + case "ushort": + case "int": + case "uint": + case "long": + case "ulong": + case "double": + case "float": + case "decimal": + case "string": + case "char": + case "object": + case "typeof": + case "sizeof": + case "null": + case "true": + case "false": + case "if": + case "else": + case "while": + case "for": + case "foreach": + case "do": + case "switch": + case "case": + case "default": + case "lock": + case "try": + case "throw": + case "catch": + case "finally": + case "goto": + case "break": + case "continue": + case "return": + case "public": + case "private": + case "internal": + case "protected": + case "static": + case "readonly": + case "sealed": + case "const": + case "new": + case "override": + case "abstract": + case "virtual": + case "partial": + case "ref": + case "out": + case "in": + case "where": + case "params": + case "this": + case "base": + case "namespace": + case "using": + case "class": + case "struct": + case "interface": + case "delegate": + case "checked": + case "get": + case "set": + case "add": + case "remove": + case "operator": + case "implicit": + case "explicit": + case "fixed": + case "extern": + case "event": + case "enum": + case "unsafe": + return true; + default: + return false; + } + } } } diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs index 48d0488d7b79e..3ad3033ae704d 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs @@ -66,9 +66,16 @@ public class Node : AbstractNode public string? VisitorName; [XmlAttribute(AttributeName = "SkipInVisitor")] - public string SkipInVisitorText; + public string? SkipInVisitorText; public bool SkipInVisitor => SkipInVisitorText == "true"; + [XmlAttribute(AttributeName = "SkipChildrenGeneration")] + public string? SkipChildrenGenerationText; + public bool SkipChildrenGeneration => SkipChildrenGenerationText == "true"; + + [XmlAttribute] + public string? ChildrenOrder; + public override bool IsAbstract => false; } @@ -90,6 +97,14 @@ public class Property public string NewText; public bool IsNew => NewText == "true"; + [XmlAttribute(AttributeName = "Internal")] + public string? IsInternalText; + public bool IsInternal => IsInternalText == "true"; + + [XmlAttribute(AttributeName = "SkipGeneration")] + public string? SkipGenerationText; + public bool SkipGeneration => SkipGenerationText == "true"; + [XmlElement(ElementName = "Comments", Type = typeof(Comments))] public Comments? Comments; } From a71301d7fce74639f2095c3f2f87d56f5dcc91e1 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 16 Aug 2019 14:53:02 -0700 Subject: [PATCH 2/5] Introduce nullable suppression to make non-boostrap compiler happy. --- .../Source/IOperationGenerator/IOperationClassWriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index c6620895e1a53..cada7e5fca667 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -397,7 +397,7 @@ private void WriteClasses() else { Debug.Assert(node.ChildrenOrder != null, $"Encountered null children order for {type.Name}, should have been caught in verifier!"); - var childrenOrdered = node.ChildrenOrder.Split(",", StringSplitOptions.RemoveEmptyEntries); + var childrenOrdered = node.ChildrenOrder!.Split(",", StringSplitOptions.RemoveEmptyEntries); foreach (var childName in childrenOrdered) { From ddee7cd544756b1965e2a8216af9674dde8dc13d Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 16 Aug 2019 16:09:21 -0700 Subject: [PATCH 3/5] Fixup xml and add more verification --- .../Operations/OperationInterfaces.xml | 11 ++++++++++- .../IOperationClassWriter.Verifier.cs | 18 ++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml index 75f4e8f813455..e2c661f17a98b 100644 --- a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml +++ b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml @@ -1069,6 +1069,15 @@ Object or collection initializer, if any. + + + Arguments of the object creation, excluding the instance argument. Arguments are in evaluation order. + + If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays. + Default values are supplied for optional arguments missing in source. + + + @@ -2012,7 +2021,7 @@ - + Represents an argument to a method invocation. diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs index 8814c50e16622..392e02d7865cc 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs @@ -47,11 +47,25 @@ private bool ModelHasErrors(Tree tree) } if (!(abstractNode is Node node)) continue; + if (node.SkipChildrenGeneration || node.SkipClassGeneration) continue; var properties = GetAllGeneratedIOperationProperties(node).Where(p => !p.IsInternal).Select(p => p.Name).ToList(); - if (properties.Count < 2) continue; - if (node.SkipChildrenGeneration || node.SkipClassGeneration) continue; + if (properties.Count < 2) + { + if (node.ChildrenOrder is string order) + { + var splitOrder = order.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList(); + + if (splitOrder.Count != properties.Count || (properties.Count == 1 && properties[0] != splitOrder[0])) + { + Console.WriteLine($"{node.Name} has inconsistent ChildrenOrder and properties"); + error = true; + } + } + continue; + } + if (node.ChildrenOrder is null) { From 401ce67c9d3a83c6047ec01c4541916fa19a64e5 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Mon, 19 Aug 2019 15:29:24 -0700 Subject: [PATCH 4/5] Use ImmutableInterlocked.InterlockedInitialize instead of CompareExchange with default, minor formatting and naming suggestions. --- .../Generated/Operations.Generated.cs | 58 +++++++++---------- .../Operations/ControlFlowGraphBuilder.cs | 6 +- .../Portable/Operations/OperationNodes.cs | 10 ++-- .../IOperationClassWriter.Verifier.cs | 11 ++-- .../IOperationClassWriter.cs | 16 ++--- 5 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs index 7e4231afd5a20..baee72579bd01 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs @@ -2805,7 +2805,7 @@ public override ImmutableArray Operations { ImmutableArray operations = CreateOperations(); SetParentOperation(operations, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyOperations, operations, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyOperations, operations); } return _lazyOperations; } @@ -2852,7 +2852,7 @@ public override ImmutableArray Declarations { ImmutableArray declarations = CreateDeclarations(); SetParentOperation(declarations, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDeclarations, declarations, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyDeclarations, declarations); } return _lazyDeclarations; } @@ -2924,7 +2924,7 @@ public override ImmutableArray Cases { ImmutableArray cases = CreateCases(); SetParentOperation(cases, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyCases, cases, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyCases, cases); } return _lazyCases; } @@ -3029,7 +3029,7 @@ public override ImmutableArray NextVariables { ImmutableArray nextVariables = CreateNextVariables(); SetParentOperation(nextVariables, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyNextVariables, nextVariables, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyNextVariables, nextVariables); } return _lazyNextVariables; } @@ -3111,7 +3111,7 @@ public override ImmutableArray Before { ImmutableArray before = CreateBefore(); SetParentOperation(before, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyBefore, before, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyBefore, before); } return _lazyBefore; } @@ -3139,7 +3139,7 @@ public override ImmutableArray AtLoopBottom { ImmutableArray atLoopBottom = CreateAtLoopBottom(); SetParentOperation(atLoopBottom, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyAtLoopBottom, atLoopBottom, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyAtLoopBottom, atLoopBottom); } return _lazyAtLoopBottom; } @@ -3286,7 +3286,7 @@ public override ImmutableArray NextVariables { ImmutableArray nextVariables = CreateNextVariables(); SetParentOperation(nextVariables, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyNextVariables, nextVariables, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyNextVariables, nextVariables); } return _lazyNextVariables; } @@ -3634,7 +3634,7 @@ public override ImmutableArray Catches { ImmutableArray catches = CreateCatches(); SetParentOperation(catches, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyCatches, catches, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyCatches, catches); } return _lazyCatches; } @@ -3908,7 +3908,7 @@ public override ImmutableArray Arguments { ImmutableArray arguments = CreateArguments(); SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArguments, arguments, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyArguments, arguments); } return _lazyArguments; } @@ -4041,7 +4041,7 @@ public override ImmutableArray Arguments { ImmutableArray arguments = CreateArguments(); SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArguments, arguments, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyArguments, arguments); } return _lazyArguments; } @@ -4107,7 +4107,7 @@ public override ImmutableArray Indices { ImmutableArray indices = CreateIndices(); SetParentOperation(indices, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyIndices, indices, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyIndices, indices); } return _lazyIndices; } @@ -4292,7 +4292,7 @@ public override ImmutableArray Arguments { ImmutableArray arguments = CreateArguments(); SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArguments, arguments, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyArguments, arguments); } return _lazyArguments; } @@ -4756,7 +4756,7 @@ public override ImmutableArray Arguments { ImmutableArray arguments = CreateArguments(); SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArguments, arguments, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyArguments, arguments); } return _lazyArguments; } @@ -4852,7 +4852,7 @@ public override ImmutableArray DimensionSizes { ImmutableArray dimensionSizes = CreateDimensionSizes(); SetParentOperation(dimensionSizes, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDimensionSizes, dimensionSizes, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyDimensionSizes, dimensionSizes); } return _lazyDimensionSizes; } @@ -5350,7 +5350,7 @@ public override ImmutableArray Parts { ImmutableArray parts = CreateParts(); SetParentOperation(parts, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyParts, parts, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyParts, parts); } return _lazyParts; } @@ -5397,7 +5397,7 @@ public override ImmutableArray Initializers { ImmutableArray initializers = CreateInitializers(); SetParentOperation(initializers, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyInitializers, initializers, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyInitializers, initializers); } return _lazyInitializers; } @@ -5444,7 +5444,7 @@ public override ImmutableArray Initializers { ImmutableArray initializers = CreateInitializers(); SetParentOperation(initializers, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyInitializers, initializers, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyInitializers, initializers); } return _lazyInitializers; } @@ -5602,7 +5602,7 @@ public override ImmutableArray Elements { ImmutableArray elements = CreateElements(); SetParentOperation(elements, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyElements, elements, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyElements, elements); } return _lazyElements; } @@ -6333,7 +6333,7 @@ public override ImmutableArray ElementValues { ImmutableArray elementValues = CreateElementValues(); SetParentOperation(elementValues, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyElementValues, elementValues, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyElementValues, elementValues); } return _lazyElementValues; } @@ -6403,7 +6403,7 @@ public override ImmutableArray IgnoredArguments { ImmutableArray ignoredArguments = CreateIgnoredArguments(); SetParentOperation(ignoredArguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyIgnoredArguments, ignoredArguments, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyIgnoredArguments, ignoredArguments); } return _lazyIgnoredArguments; } @@ -6463,7 +6463,7 @@ public override ImmutableArray Declarators { ImmutableArray declarators = CreateDeclarators(); SetParentOperation(declarators, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDeclarators, declarators, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyDeclarators, declarators); } return _lazyDeclarators; } @@ -6491,7 +6491,7 @@ public override ImmutableArray IgnoredDimensions { ImmutableArray ignoredDimensions = CreateIgnoredDimensions(); SetParentOperation(ignoredDimensions, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyIgnoredDimensions, ignoredDimensions, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyIgnoredDimensions, ignoredDimensions); } return _lazyIgnoredDimensions; } @@ -6688,7 +6688,7 @@ public override ImmutableArray Clauses { ImmutableArray clauses = CreateClauses(); SetParentOperation(clauses, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyClauses, clauses, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyClauses, clauses); } return _lazyClauses; } @@ -6702,7 +6702,7 @@ public override ImmutableArray Body { ImmutableArray body = CreateBody(); SetParentOperation(body, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyBody, body, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyBody, body); } return _lazyBody; } @@ -7520,7 +7520,7 @@ public override ImmutableArray Clauses { ImmutableArray clauses = CreateClauses(); SetParentOperation(clauses, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyClauses, clauses, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyClauses, clauses); } return _lazyClauses; } @@ -7586,7 +7586,7 @@ public override ImmutableArray DimensionSizes { ImmutableArray dimensionSizes = CreateDimensionSizes(); SetParentOperation(dimensionSizes, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDimensionSizes, dimensionSizes, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyDimensionSizes, dimensionSizes); } return _lazyDimensionSizes; } @@ -7649,7 +7649,7 @@ public override ImmutableArray DeconstructionSubpatterns { ImmutableArray deconstructionSubpatterns = CreateDeconstructionSubpatterns(); SetParentOperation(deconstructionSubpatterns, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyDeconstructionSubpatterns, deconstructionSubpatterns, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyDeconstructionSubpatterns, deconstructionSubpatterns); } return _lazyDeconstructionSubpatterns; } @@ -7663,7 +7663,7 @@ public override ImmutableArray PropertySubpatterns { ImmutableArray propertySubpatterns = CreatePropertySubpatterns(); SetParentOperation(propertySubpatterns, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyPropertySubpatterns, propertySubpatterns, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyPropertySubpatterns, propertySubpatterns); } return _lazyPropertySubpatterns; } @@ -7737,7 +7737,7 @@ public override ImmutableArray Arms { ImmutableArray arms = CreateArms(); SetParentOperation(arms, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArms, arms, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyArms, arms); } return _lazyArms; } diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs index c6351ea2de8f3..a40d6c6423088 100644 --- a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs @@ -3504,7 +3504,7 @@ private void AddExceptionStore(ITypeSymbol exceptionType, IOperation exceptionDe if (exceptionTarget != null) { AddStatement(new SimpleAssignmentOperation( - isRef: false, + isRef: false, target: exceptionTarget, value: new CaughtExceptionOperation(syntax, exceptionType), semanticModel: null, @@ -4228,8 +4228,8 @@ IOperation getLoopControlVariableAssignment(IOperation current) operation.LoopControlVariable.Syntax, operation.LoopControlVariable.Type, constantValue: default, isImplicit: true); default: - return new SimpleAssignmentOperation(isRef: false, - Visit(operation.LoopControlVariable), // In C# this is an error case and VB doesn't support ref locals + return new SimpleAssignmentOperation(isRef: false, // In C# this is an error case and VB doesn't support ref locals + Visit(operation.LoopControlVariable), current, semanticModel: null, operation.LoopControlVariable.Syntax, operation.LoopControlVariable.Type, constantValue: default, isImplicit: true); diff --git a/src/Compilers/Core/Portable/Operations/OperationNodes.cs b/src/Compilers/Core/Portable/Operations/OperationNodes.cs index 790c128be4c2d..61e649909c73b 100644 --- a/src/Compilers/Core/Portable/Operations/OperationNodes.cs +++ b/src/Compilers/Core/Portable/Operations/OperationNodes.cs @@ -60,7 +60,7 @@ public override IEnumerable Children { ImmutableArray children = GetChildren(); SetParentOperation(children, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyChildrenInterlocked, children, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyChildrenInterlocked, children); } return _lazyChildrenInterlocked; @@ -246,7 +246,7 @@ public override IEnumerable Children { ImmutableArray children = CreateChildren(); SetParentOperation(children, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyChildrenInterlocked, children, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyChildrenInterlocked, children); } return _lazyChildrenInterlocked; @@ -452,7 +452,7 @@ public override ImmutableArray Arguments { ImmutableArray arguments = CreateArguments(); SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyArgumentsInterlocked, arguments); } return _lazyArgumentsInterlocked; @@ -557,7 +557,7 @@ public override ImmutableArray Arguments { ImmutableArray arguments = CreateArguments(); SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyArgumentsInterlocked, arguments); } return _lazyArgumentsInterlocked; @@ -647,7 +647,7 @@ public override ImmutableArray Arguments { ImmutableArray arguments = CreateArguments(); SetParentOperation(arguments, this); - ImmutableInterlocked.InterlockedCompareExchange(ref _lazyArgumentsInterlocked, arguments, default); + ImmutableInterlocked.InterlockedInitialize(ref _lazyArgumentsInterlocked, arguments); } return _lazyArgumentsInterlocked; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs index 392e02d7865cc..c90dc25f3e60a 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Linq; namespace IOperationGenerator @@ -20,6 +22,7 @@ private bool ModelHasErrors(Tree tree) if (!abstractNode.Name.EndsWith("Operation")) { Console.WriteLine($"All IOperation node names must end with Operation. {abstractNode.Name} does not."); + error = true; } if (!_typeMap.ContainsKey(abstractNode.Base)) @@ -40,7 +43,7 @@ private bool ModelHasErrors(Tree tree) { if (prop.Comments?.Elements?[0].Name != "summary" && !prop.IsInternal) { - Console.WriteLine($"{abstractNode.Name}.{prop.Name} does not have correctly formatted comments, please ensure that there is a block for the type."); + Console.WriteLine($"{abstractNode.Name}.{prop.Name} does not have correctly formatted comments, please ensure that there is a block for the property."); error = true; } } @@ -69,13 +72,13 @@ private bool ModelHasErrors(Tree tree) if (node.ChildrenOrder is null) { - Console.WriteLine($"{node.Name} has more than 1 IOperation properties and must declare an explicit ordering with the ChildrenOrder attribute."); + Console.WriteLine($"{node.Name} has more than 1 IOperation property and must declare an explicit ordering with the ChildrenOrder attribute."); Console.WriteLine($"Properties: {string.Join(", ", properties)}"); error = true; continue; } - var childrenOrdered = node.ChildrenOrder.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList(); + var childrenOrdered = GetPropertyOrder(node); foreach (var child in childrenOrdered) { if (!properties.Remove(child)) diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index cada7e5fca667..1a302023e0885 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -349,9 +349,9 @@ private void WriteClasses() var allProps = GetAllProperties(type); bool hasSkippedProperties = !GetAllProperties(type, includeSkipGenerationProperties: true).SequenceEqual(allProps); - var ioperationTypes = allProps.Where(p => IsIOperationType(p.Type)).ToList(); - var publicIOperationTypes = ioperationTypes.Where(p => !p.IsInternal).ToList(); - var hasIOpChildren = ioperationTypes.Count != 0; + var ioperationProperties = allProps.Where(p => IsIOperationType(p.Type)).ToList(); + var publicIOperationTypes = ioperationProperties.Where(p => !p.IsInternal).ToList(); + var hasIOpChildren = ioperationProperties.Count != 0; var constructorAccessibility = type.IsAbstract ? "protected" : "internal"; string typeName = type.Name[1..]; @@ -397,7 +397,7 @@ private void WriteClasses() else { Debug.Assert(node.ChildrenOrder != null, $"Encountered null children order for {type.Name}, should have been caught in verifier!"); - var childrenOrdered = node.ChildrenOrder!.Split(",", StringSplitOptions.RemoveEmptyEntries); + var childrenOrdered = GetPropertyOrder(node); foreach (var childName in childrenOrdered) { @@ -469,7 +469,7 @@ void writeIfCheck(string memberName) if (hasIOpChildren) { - foreach (var property in ioperationTypes) + foreach (var property in ioperationProperties) { writeProperty(property, propExtensibility: "override "); } @@ -497,7 +497,7 @@ void writeIfCheck(string memberName) writeClassHeader("abstract", @class, @base, type.Name); - var propertiesAndFieldNames = ioperationTypes.Select(i => (i, $"_lazy{i.Name}", $"s_unset{GetSubName(i.Type)}")).ToList(); + var propertiesAndFieldNames = ioperationProperties.Select(i => (i, $"_lazy{i.Name}", $"s_unset{GetSubName(i.Type)}")).ToList(); foreach (var (prop, name, unset) in propertiesAndFieldNames) { @@ -526,7 +526,7 @@ void writeIfCheck(string memberName) var localName = prop.Name.ToCamelCase(); WriteLine($"{prop.Type} {localName} = Create{prop.Name}();"); WriteLine($"SetParentOperation({localName}, this);"); - WriteLine($"ImmutableInterlocked.InterlockedCompareExchange(ref {fieldName}, {localName}, default);"); + WriteLine($"ImmutableInterlocked.InterlockedInitialize(ref {fieldName}, {localName});"); Unbrace(); } @@ -793,6 +793,8 @@ private static bool IsImmutableArray(string typeName, [NotNullWhen(true)] out st return false; } + private static List GetPropertyOrder(Node node) => node.ChildrenOrder?.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList() ?? new List(); + private enum ClassType { Abstract, From dff485130dd8ee52e58017a4a7600e03f0afb8f4 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Mon, 19 Aug 2019 16:16:00 -0700 Subject: [PATCH 5/5] Fixup name and use refactored method in one more place. --- .../IOperationClassWriter.Verifier.cs | 2 +- .../IOperationGenerator/IOperationClassWriter.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs index c90dc25f3e60a..ee33a99940318 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs @@ -58,7 +58,7 @@ private bool ModelHasErrors(Tree tree) { if (node.ChildrenOrder is string order) { - var splitOrder = order.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList(); + var splitOrder = GetPropertyOrder(node); if (splitOrder.Count != properties.Count || (properties.Count == 1 && properties[0] != splitOrder[0])) { diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index 1a302023e0885..c152b82cf87dd 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -350,7 +350,7 @@ private void WriteClasses() var allProps = GetAllProperties(type); bool hasSkippedProperties = !GetAllProperties(type, includeSkipGenerationProperties: true).SequenceEqual(allProps); var ioperationProperties = allProps.Where(p => IsIOperationType(p.Type)).ToList(); - var publicIOperationTypes = ioperationProperties.Where(p => !p.IsInternal).ToList(); + var publicIOperationProps = ioperationProperties.Where(p => !p.IsInternal).ToList(); var hasIOpChildren = ioperationProperties.Count != 0; var constructorAccessibility = type.IsAbstract ? "protected" : "internal"; string typeName = type.Name[1..]; @@ -386,13 +386,13 @@ private void WriteClasses() { if (!node.SkipChildrenGeneration) { - if (publicIOperationTypes.Count > 0) + if (publicIOperationProps.Count > 0) { var orderedProperties = new List(); - if (publicIOperationTypes.Count == 1) + if (publicIOperationProps.Count == 1) { - orderedProperties.Add(publicIOperationTypes.Single()); + orderedProperties.Add(publicIOperationProps.Single()); } else { @@ -401,7 +401,7 @@ private void WriteClasses() foreach (var childName in childrenOrdered) { - orderedProperties.Add(publicIOperationTypes.Find(p => p.Name == childName) ?? + orderedProperties.Add(publicIOperationProps.Find(p => p.Name == childName) ?? throw new InvalidOperationException($"Cannot find property for {childName}")); } }