/// <summary> /// Writes down the C# overload of a feature. /// </summary> /// <param name="writer">The stream on which to write.</param> /// <param name="featureTextType">The write mode.</param> /// <param name="isOverride">True if the feature is an override.</param> /// <param name="nameString">The composed feature name.</param> /// <param name="exportStatus">The feature export status.</param> /// <param name="isConstructor">True if the feature is a constructor.</param> /// <param name="isFirstFeature">True if the feature is the first in a list.</param> /// <param name="isMultiline">True if there is a separating line above.</param> public void WriteCSharp(ICSharpWriter writer, CSharpFeatureTextTypes featureTextType, bool isOverride, string nameString, CSharpExports exportStatus, bool isConstructor, ref bool isFirstFeature, ref bool isMultiline) { Debug.Assert(WriteDown); IList <ICSharpParameter> SelectedParameterList = ParameterList; IList <ICSharpParameter> SelectedResultList = ResultList; if (isOverride && Precursor != null) { SelectedParameterList = Precursor.ParameterList; SelectedResultList = Precursor.ResultList; } CSharpArgument.BuildParameterList(writer, SelectedParameterList, SelectedResultList, featureTextType, out string ArgumentEntityList, out string ArgumentNameList, out string ResultType); string ExportStatusText; if (featureTextType == CSharpFeatureTextTypes.Implementation) { bool IsHandled = false; switch (Body) { case ICSharpDeferredBody AsDeferredBody: CSharpAssertion.WriteContract(writer, AsDeferredBody.RequireList, AsDeferredBody.EnsureList, CSharpContractLocations.Other, true, ref isFirstFeature, ref isMultiline); ExportStatusText = CSharpNames.ComposedExportStatus(false, true, false, exportStatus); writer.WriteIndentedLine($"{ExportStatusText} {ResultType} {nameString}({ArgumentEntityList});"); isMultiline = false; IsHandled = true; break; case ICSharpEffectiveBody AsEffectiveBody: CSharpAssertion.WriteContract(writer, AsEffectiveBody.RequireList, AsEffectiveBody.EnsureList, CSharpContractLocations.Other, true, ref isFirstFeature, ref isMultiline); CSharpBodyFlags Flags = CSharpBodyFlags.MandatoryCurlyBrackets; string ResultString = string.Empty; List <string> InitialisationStringList = new List <string>(); if (ResultList.Count == 1) { Flags |= CSharpBodyFlags.HasResult; ICSharpParameter Result = ResultList[0]; ResultString = Result.Feature.Type.Type2CSharpString(writer, CSharpTypeFormats.AsInterface, CSharpNamespaceFormats.None); } else { if (ResultType != "void") { Flags |= CSharpBodyFlags.HasResult; ResultString = ResultType; } foreach (ICSharpParameter Item in ResultList) { string InitValueString; ICSharpType ResultEntityType = Item.Feature.Type; if (ResultEntityType is ICSharpClassType AsClassType) { // TODO: when the type inherit from Enumeration if (AsClassType.Class.Source.ClassGuid == LanguageClasses.AnyOptionalReference.Guid) { InitValueString = "new OptionalReference<>(null)"; // TODO } else if (AsClassType.Class.Source.ClassGuid == LanguageClasses.String.Guid) { InitValueString = "\"\""; } else if (AsClassType.Class.Source.ClassGuid == LanguageClasses.Boolean.Guid) { InitValueString = "false"; } else if (AsClassType.Class.Source.ClassGuid == LanguageClasses.Character.Guid) { InitValueString = "'\0'"; } else if (AsClassType.Class.Source.ClassGuid == LanguageClasses.Number.Guid) { InitValueString = "0"; } else { InitValueString = "null"; } } else { InitValueString = "null"; // TODO : tuples } string InitNameString = CSharpNames.ToCSharpIdentifier(Item.Name); InitialisationStringList.Add($"{InitNameString} = {InitValueString};"); } } ExportStatusText = CSharpNames.ComposedExportStatus(isOverride, false, false, exportStatus); writer.WriteIndentedLine($"{ExportStatusText} {ResultType} {nameString}({ArgumentEntityList})"); AsEffectiveBody.WriteCSharp(writer, Flags, ResultString, false, InitialisationStringList); isMultiline = true; IsHandled = true; break; case ICSharpPrecursorBody AsPrecursorBody: if (isMultiline) { writer.WriteEmptyLine(); } ExportStatusText = CSharpNames.ComposedExportStatus(true, false, false, exportStatus); writer.WriteIndentedLine($"{ExportStatusText} {ResultType} {nameString}({ArgumentEntityList})"); writer.WriteIndentedLine("{"); writer.IncreaseIndent(); writer.WriteIndentedLine($"return base.{nameString}({ArgumentNameList});"); writer.DecreaseIndent(); writer.WriteIndentedLine("}"); isMultiline = true; IsHandled = true; break; } Debug.Assert(IsHandled); } else { writer.WriteIndentedLine($"{ResultType} {nameString}({ArgumentEntityList});"); isMultiline = false; } }
/// <summary> /// Writes down the body source code. /// </summary> /// <param name="writer">The stream on which to write down.</param> /// <param name="flags">Some flags.</param> /// <param name="resultType">Type of the result, if any.</param> /// <param name="skipFirstInstruction">Skip the first instruction.</param> /// <param name="initialisationStringList">List of initializations.</param> public virtual void WriteCSharp(ICSharpWriter writer, CSharpBodyFlags flags, string resultType, bool skipFirstInstruction, IList <string> initialisationStringList) { Debug.Assert(WriteDown); writer.WriteIndentedLine("{"); writer.IncreaseIndent(); IList <ICSharpAssertion> EffectiveRequireList = RequireList; IList <ICSharpAssertion> EffectiveEnsureList = EnsureList; switch (ParentFeature) { case ICSharpFunctionFeature AsFunctionFeature: if (AsFunctionFeature.OriginalPrecursor != null) { ICSharpQueryOverload ParentOverload = null; foreach (ICSharpQueryOverload Overload in AsFunctionFeature.OverloadList) { if (Overload.Body == this) { ParentOverload = Overload; break; } } Debug.Assert(ParentOverload != null); ICSharpQueryOverload ParentPrecursorOverload = ParentOverload.Precursor; if (ParentPrecursorOverload != null) { ICSharpBody PrecursorBody = ParentPrecursorOverload.Body; if (RequireList.Count == 0 && PrecursorBody.RequireList.Count > 0) { EffectiveRequireList = PrecursorBody.RequireList; } if (EnsureList.Count == 0 && PrecursorBody.EnsureList.Count > 0) { EffectiveEnsureList = PrecursorBody.EnsureList; } } } break; case ICSharpProcedureFeature AsProcedureFeature: if (AsProcedureFeature.OriginalPrecursor != null) { ICSharpCommandOverload ParentOverload = null; foreach (ICSharpCommandOverload Overload in AsProcedureFeature.OverloadList) { if (Overload.Body == this) { ParentOverload = Overload; break; } } Debug.Assert(ParentOverload != null); ICSharpCommandOverload ParentPrecursorOverload = ParentOverload.Precursor; if (ParentPrecursorOverload != null) { ICSharpBody PrecursorBody = ParentPrecursorOverload.Body; if (RequireList.Count == 0 && PrecursorBody.RequireList.Count > 0) { EffectiveRequireList = PrecursorBody.RequireList; } if (EnsureList.Count == 0 && PrecursorBody.EnsureList.Count > 0) { EffectiveEnsureList = PrecursorBody.EnsureList; } } } break; case ICSharpPropertyFeature AsPropertyFeature: if (AsPropertyFeature.OriginalPrecursor != null) { ICSharpBody PrecursorBody = null; if (this == AsPropertyFeature.GetterBody) { PrecursorBody = AsPropertyFeature.OriginalPrecursor.GetterBody; } else if (this == AsPropertyFeature.SetterBody) { PrecursorBody = AsPropertyFeature.OriginalPrecursor.SetterBody; } if (PrecursorBody != null) { if (RequireList.Count == 0 && PrecursorBody.RequireList.Count > 0) { EffectiveRequireList = PrecursorBody.RequireList; } if (EnsureList.Count == 0 && PrecursorBody.EnsureList.Count > 0) { EffectiveEnsureList = PrecursorBody.EnsureList; } } } break; case ICSharpIndexerFeature AsIndexerFeature: if (AsIndexerFeature.OriginalPrecursor != null) { ICSharpBody PrecursorBody = null; if (this == AsIndexerFeature.GetterBody) { PrecursorBody = AsIndexerFeature.OriginalPrecursor.GetterBody; } else if (this == AsIndexerFeature.SetterBody) { PrecursorBody = AsIndexerFeature.OriginalPrecursor.SetterBody; } if (PrecursorBody != null) { if (RequireList.Count == 0 && PrecursorBody.RequireList.Count > 0) { EffectiveRequireList = PrecursorBody.RequireList; } if (EnsureList.Count == 0 && PrecursorBody.EnsureList.Count > 0) { EffectiveEnsureList = PrecursorBody.EnsureList; } } } break; } foreach (ICSharpAssertion Assertion in EffectiveRequireList) { Assertion.WriteCSharp(writer); } if (EffectiveRequireList.Count > 0) { writer.WriteEmptyLine(); } /*TODO * List<AttachmentAlias> AttachmentVariableTable = new List<AttachmentAlias>(); * foreach (IInstruction Item in BodyInstructionList) * Item.AddAttachmentVariables(Context, AttachmentVariableTable); */ if (flags.HasFlag(CSharpBodyFlags.HasResult)) { writer.WriteIndentedLine($"{resultType} Result = default;"); } foreach (ICSharpScopeAttributeFeature Item in EntityDeclarationList) { Item.WriteCSharp(writer); } /*TODO * foreach (AttachmentAlias AliasItem in AttachmentVariableTable) * { * string AttachedVariableName = AliasItem.EntityName; * string AttachmentTypeString = CSharpTypes.Type2CSharpString(AliasItem.EntityType, Context, AliasItem.AttachmentFormat, CSharpNamespaceFormats.None); * * writer.WriteIndentedLine(AttachmentTypeString + " " + AttachedVariableName + ";"); * Context.AttachmentVariableTable.Add(AliasItem); * } */ if (flags.HasFlag(CSharpBodyFlags.HasResult) || EntityDeclarationList.Count > 0 /* || AttachmentVariableTable.Count > 0*/) { writer.WriteEmptyLine(); } foreach (string s in initialisationStringList) { writer.WriteIndentedLine(s); } if (initialisationStringList.Count > 0) { writer.WriteEmptyLine(); } for (int i = 0; i < BodyInstructionList.Count; i++) { if (i == 0 && skipFirstInstruction) { continue; } ICSharpInstruction Item = BodyInstructionList[i]; Item.WriteCSharp(writer); } if (EffectiveEnsureList.Count > 0) { writer.WriteEmptyLine(); foreach (ICSharpAssertion Assertion in EffectiveEnsureList) { Assertion.WriteCSharp(writer); } if (flags.HasFlag(CSharpBodyFlags.HasResult)) { writer.WriteEmptyLine(); } } // TODO: ExceptionHandlerList if (ParentFeature.Owner.HasCheckInvariant) { writer.WriteEmptyLine(); writer.WriteIndentedLine("CheckInvariant();"); } if (flags.HasFlag(CSharpBodyFlags.HasResult)) { writer.WriteIndentedLine("return Result;"); } /*TODO * foreach (AttachmentAlias AliasItem in AttachmentVariableTable) * Context.AttachmentVariableTable.Remove(AliasItem); */ writer.DecreaseIndent(); writer.WriteIndentedLine("}"); }