private void AccessTupleFields(BoundDeconstructionAssignmentOperator node, BoundDeconstructionDeconstructStep deconstruction, ArrayBuilder<LocalSymbol> temps, ArrayBuilder<BoundExpression> stores, ArrayBuilder<BoundValuePlaceholderBase> placeholders) { var target = PlaceholderReplacement(deconstruction.TargetPlaceholder); var tupleType = target.Type.IsTupleType ? target.Type : TupleTypeSymbol.Create((NamedTypeSymbol)target.Type); var tupleElementTypes = tupleType.TupleElementTypes; var numElements = tupleElementTypes.Length; CSharpSyntaxNode syntax = node.Syntax; // save the target as we need to access it multiple times BoundAssignmentOperator assignmentToTemp; var savedTuple = _factory.StoreToTemp(target, out assignmentToTemp); stores.Add(assignmentToTemp); temps.Add(savedTuple.LocalSymbol); // list the tuple fields accessors var fields = tupleType.TupleElementFields; for (int i = 0; i < numElements; i++) { var field = fields[i]; DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic(); if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error) { Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, syntax.Location); } var fieldAccess = MakeTupleFieldAccess(syntax, field, savedTuple, null, LookupResultKind.Empty); AddPlaceholderReplacement(deconstruction.OutputPlaceholders[i], fieldAccess); placeholders.Add(deconstruction.OutputPlaceholders[i]); } }
/// <summary> /// Takes the outputs from the previous deconstructionStep and depending on the structure of variables, will generate further deconstructions, or simply assignments. /// Returns true for success, but false if has errors. /// </summary> private bool DeconstructOrAssignOutputs( BoundDeconstructionDeconstructStep deconstructionStep, ArrayBuilder <DeconstructionVariable> variables, CSharpSyntaxNode syntax, DiagnosticBag diagnostics, ArrayBuilder <BoundDeconstructionDeconstructStep> deconstructionSteps, ArrayBuilder <BoundDeconstructionAssignmentStep> assignmentSteps) { bool hasErrors = false; int count = variables.Count; for (int i = 0; i < count; i++) { var variable = variables[i]; var valuePlaceholder = deconstructionStep.OutputPlaceholders[i]; if (variable.HasNestedVariables) { var nested = variable.NestedVariables; if (!DeconstructIntoSteps(valuePlaceholder, syntax, diagnostics, nested, deconstructionSteps, assignmentSteps)) { hasErrors = true; } } else { var assignment = MakeDeconstructionAssignmentStep(variable.Single, valuePlaceholder.Type, valuePlaceholder, syntax, diagnostics); assignmentSteps.Add(assignment); } } return(!hasErrors); }
private void AccessTupleFields(BoundDeconstructionAssignmentOperator node, BoundDeconstructionDeconstructStep deconstruction, ArrayBuilder <LocalSymbol> temps, ArrayBuilder <BoundExpression> stores, ArrayBuilder <BoundValuePlaceholderBase> placeholders) { var target = PlaceholderReplacement(deconstruction.InputPlaceholder); var tupleType = target.Type.IsTupleType ? target.Type : TupleTypeSymbol.Create((NamedTypeSymbol)target.Type); var tupleElementTypes = tupleType.TupleElementTypes; var numElements = tupleElementTypes.Length; SyntaxNode syntax = node.Syntax; // save the target as we need to access it multiple times BoundAssignmentOperator assignmentToTemp; BoundLocal savedTuple = _factory.StoreToTemp(target, out assignmentToTemp); stores.Add(assignmentToTemp); temps.Add(savedTuple.LocalSymbol); // list the tuple fields accessors var fields = tupleType.TupleElements; for (int i = 0; i < numElements; i++) { var field = fields[i]; DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic(); if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error) { Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, syntax.Location); } var fieldAccess = MakeTupleFieldAccess(syntax, field, savedTuple, null, LookupResultKind.Empty); AddPlaceholderReplacement(deconstruction.OutputPlaceholders[i], fieldAccess); placeholders.Add(deconstruction.OutputPlaceholders[i]); } }
/// <summary> /// Prepares local variables to be used in Deconstruct call /// Adds a invocation of Deconstruct with those as out parameters onto the 'stores' sequence /// Returns the expressions for those out parameters /// </summary> private void CallDeconstruct(BoundDeconstructionAssignmentOperator node, BoundDeconstructionDeconstructStep deconstruction, ArrayBuilder <LocalSymbol> temps, ArrayBuilder <BoundExpression> stores, ArrayBuilder <BoundValuePlaceholderBase> placeholders) { Debug.Assert((object)deconstruction.DeconstructInvocationOpt != null); SyntaxNode syntax = node.Syntax; // prepare out parameters for Deconstruct var deconstructParameters = deconstruction.OutputPlaceholders; var outParametersBuilder = ArrayBuilder <BoundExpression> .GetInstance(deconstructParameters.Length); for (var i = 0; i < deconstructParameters.Length; i++) { var deconstructParameter = deconstructParameters[i]; var localSymbol = new SynthesizedLocal(_factory.CurrentMethod, deconstructParameter.Type, SynthesizedLocalKind.LoweringTemp); var localBound = new BoundLocal(syntax, localSymbol, null, deconstructParameter.Type ) { WasCompilerGenerated = true }; temps.Add(localSymbol); outParametersBuilder.Add(localBound); AddPlaceholderReplacement(deconstruction.OutputPlaceholders[i], localBound); placeholders.Add(deconstruction.OutputPlaceholders[i]); } var outParameters = outParametersBuilder.ToImmutableAndFree(); // invoke Deconstruct with placeholders replaced by locals stores.Add(VisitExpression(deconstruction.DeconstructInvocationOpt)); }
/// <summary> /// Prepares local variables to be used in Deconstruct call /// Adds a invocation of Deconstruct with those as out parameters onto the 'stores' sequence /// Returns the expressions for those out parameters /// </summary> private void CallDeconstruct(BoundDeconstructionAssignmentOperator node, BoundDeconstructionDeconstructStep deconstruction, ArrayBuilder<LocalSymbol> temps, ArrayBuilder<BoundExpression> stores, ArrayBuilder<BoundValuePlaceholderBase> placeholders) { Debug.Assert((object)deconstruction.DeconstructInvocationOpt != null); CSharpSyntaxNode syntax = node.Syntax; // prepare out parameters for Deconstruct var deconstructParameters = deconstruction.OutputPlaceholders; var outParametersBuilder = ArrayBuilder<BoundExpression>.GetInstance(deconstructParameters.Length); for (var i = 0; i < deconstructParameters.Length; i++) { var deconstructParameter = deconstructParameters[i]; var localSymbol = new SynthesizedLocal(_factory.CurrentMethod, deconstructParameter.Type, SynthesizedLocalKind.LoweringTemp); var localBound = new BoundLocal(syntax, localSymbol, null, deconstructParameter.Type ) { WasCompilerGenerated = true }; temps.Add(localSymbol); outParametersBuilder.Add(localBound); AddPlaceholderReplacement(deconstruction.OutputPlaceholders[i], localBound); placeholders.Add(deconstruction.OutputPlaceholders[i]); } var outParameters = outParametersBuilder.ToImmutableAndFree(); // invoke Deconstruct with placeholders replaced by locals stores.Add(VisitExpression(deconstruction.DeconstructInvocationOpt)); }
/// <summary> /// Takes the outputs from the previous deconstructionStep and depending on the structure of variables, will: /// - generate further deconstructions, /// - or simply conversions and assignments. /// /// Returns true for success, but false if has errors. /// </summary> private bool DeconstructOrAssignOutputs( BoundDeconstructionDeconstructStep deconstructionStep, ArrayBuilder<DeconstructionVariable> variables, CSharpSyntaxNode syntax, DiagnosticBag diagnostics, ArrayBuilder<BoundDeconstructionDeconstructStep> deconstructionSteps, ArrayBuilder<BoundDeconstructionAssignmentStep> conversionSteps, ArrayBuilder<BoundDeconstructionAssignmentStep> assignmentSteps, ArrayBuilder<BoundDeconstructionConstructionStep> constructionStepsOpt) { bool hasErrors = false; var constructionInputs = constructionStepsOpt == null ? null : ArrayBuilder<BoundDeconstructValuePlaceholder>.GetInstance(); int count = variables.Count; for (int i = 0; i < count; i++) { var variable = variables[i]; var valuePlaceholder = deconstructionStep.OutputPlaceholders[i]; if (variable.HasNestedVariables) { var nested = variable.NestedVariables; if (!DeconstructIntoSteps(valuePlaceholder, syntax, diagnostics, nested, deconstructionSteps, conversionSteps, assignmentSteps, constructionStepsOpt)) { hasErrors = true; } else if (constructionInputs != null) { constructionInputs.Add(constructionStepsOpt.Last().OutputPlaceholder); } } else { var conversion = MakeDeconstructionAssignmentStep(variable.Single, valuePlaceholder, syntax, diagnostics); conversionSteps.Add(conversion); var assignment = MakeDeconstructionAssignmentStep(variable.Single, conversion.OutputPlaceholder, syntax, diagnostics); assignmentSteps.Add(assignment); if (constructionInputs != null) { constructionInputs.Add(conversion.OutputPlaceholder); } } } if (constructionStepsOpt != null) { if (hasErrors) { constructionInputs.Free(); } else { var construct = MakeDeconstructionConstructionStep(syntax, diagnostics, constructionInputs.ToImmutableAndFree()); constructionStepsOpt.Add(construct); } } return !hasErrors; }
/// <summary> /// Takes the outputs from the previous deconstructionStep and depending on the structure of variables, will generate further deconstructions, or simply assignments. /// Returns true for success, but false if has errors. /// </summary> private bool DeconstructOrAssignOutputs( BoundDeconstructionDeconstructStep deconstructionStep, ArrayBuilder<DeconstructionVariable> variables, CSharpSyntaxNode syntax, DiagnosticBag diagnostics, ArrayBuilder<BoundDeconstructionDeconstructStep> deconstructionSteps, ArrayBuilder<BoundDeconstructionAssignmentStep> assignmentSteps) { bool hasErrors = false; int count = variables.Count; for (int i = 0; i < count; i++) { var variable = variables[i]; var valuePlaceholder = deconstructionStep.OutputPlaceholders[i]; if (variable.HasNestedVariables) { var nested = variable.NestedVariables; if (!DeconstructIntoSteps(valuePlaceholder, syntax, diagnostics, nested, deconstructionSteps, assignmentSteps)) { hasErrors = true; } } else { var assignment = MakeDeconstructionAssignmentStep(variable.Single, valuePlaceholder.Type, valuePlaceholder, syntax, diagnostics); assignmentSteps.Add(assignment); } } return !hasErrors; }
/// <summary> /// Takes the outputs from the previous deconstructionStep and depending on the structure of variables, will: /// - generate further deconstructions, /// - or simply conversions and assignments. /// /// Returns true for success, but false if has errors. /// </summary> private bool DeconstructOrAssignOutputs( BoundDeconstructionDeconstructStep deconstructionStep, ArrayBuilder <DeconstructionVariable> variables, CSharpSyntaxNode syntax, DiagnosticBag diagnostics, ArrayBuilder <BoundDeconstructionDeconstructStep> deconstructionSteps, ArrayBuilder <BoundDeconstructionAssignmentStep> conversionSteps, ArrayBuilder <BoundDeconstructionAssignmentStep> assignmentSteps, ArrayBuilder <BoundDeconstructionConstructionStep> constructionStepsOpt) { bool hasErrors = false; var constructionInputs = constructionStepsOpt == null ? null : ArrayBuilder <BoundDeconstructValuePlaceholder> .GetInstance(); int count = variables.Count; for (int i = 0; i < count; i++) { var variable = variables[i]; var valuePlaceholder = deconstructionStep.OutputPlaceholders[i]; if (variable.HasNestedVariables) { var nested = variable.NestedVariables; if (!DeconstructIntoSteps(valuePlaceholder, syntax, diagnostics, nested, deconstructionSteps, conversionSteps, assignmentSteps, constructionStepsOpt)) { hasErrors = true; } else if (constructionInputs != null) { constructionInputs.Add(constructionStepsOpt.Last().OutputPlaceholder); } } else { var conversion = MakeDeconstructionAssignmentStep(variable.Single, valuePlaceholder, syntax, diagnostics); conversionSteps.Add(conversion); var assignment = MakeDeconstructionAssignmentStep(variable.Single, conversion.OutputPlaceholder, syntax, diagnostics); assignmentSteps.Add(assignment); if (constructionInputs != null) { constructionInputs.Add(conversion.OutputPlaceholder); } } } if (constructionStepsOpt != null) { if (hasErrors) { constructionInputs.Free(); } else { var construct = MakeDeconstructionConstructionStep(syntax, diagnostics, constructionInputs.ToImmutableAndFree()); constructionStepsOpt.Add(construct); } } return(!hasErrors); }