/// <summary> /// Initializes a new instance. This instance is accessible via <see cref="Current"/> until /// <see cref="Dispose"/> is called. /// </summary> public CompilingContext() { Current = this; }
/// <inheritdoc /> public void Dispose() { Current = null; }
/// <summary> /// Compiles the given <paramref name="buddyText"/> into a TDIL file as string. /// </summary> /// <param name="buddyText">Buddy language text to compile</param> /// <returns>Compiled buddy text</returns> /// <exception cref="ArgumentNullException">If the given <paramref name="buddyText"/> is NULL or empty</exception> /// <exception cref="BuddyCompilerException">If something went wrong during the compilation process</exception> public virtual string Compile(string buddyText) { if (string.IsNullOrEmpty(buddyText)) { throw new ArgumentNullException(nameof(buddyText)); } StopwatchLog compilerStopwatch = StopwatchLog.StartNew(LogCompilerPerformance); TdilFileWriter tdilFileWriter = new TdilFileWriter("0.1.2"); try { // TODO Remove workaround add 'Vorbedingung' if (!buddyText.Contains("Vorbedingung: -") && buddyText.Contains("Anwendung: ")) { int insertPoint = buddyText.IndexOf("Schritte:"); buddyText = buddyText.Insert(insertPoint, "Vorbedingung: -\r\n\r\n"); } // TODO Remove workaround add final linefeeds if (!buddyText.EndsWith("\r\n")) { buddyText += "\r\n"; } // Process text StopwatchLog textProcessorStopwatch = StopwatchLog.StartNew(LogBuddyTextProcessorPerformance); BuddyTextInfo buddyTextInfo = _buddyTextProcessor.ProcessText(buddyText); textProcessorStopwatch.Dispose(buddyTextInfo); // In the case of an short form, create standard names if (buddyTextInfo.IsShortForm) { buddyTextInfo.ApplicationText = "untitled"; buddyTextInfo.UseCaseText = "untitled"; buddyTextInfo.ScenarioText = "untitled"; } // TODO Check if this is a workaround and remove it if (string.IsNullOrEmpty(buddyTextInfo.VersionText)) { buddyTextInfo.VersionText = "*"; } // Little verification ushort expectedNoOfSteps = CalculateNoOfSteps(buddyText); if (expectedNoOfSteps != buddyTextInfo.Steps.Length) { ThrowUncompilableDirectiveException(buddyText, expectedNoOfSteps, buddyTextInfo.Steps.Length); } string[] buddyTextSteps = buddyTextInfo.Steps; // Normalize directives string[] normalizedBuddyTextSteps; using (StopwatchLog.StartNew(LogNormalizingPerformance)) { normalizedBuddyTextSteps = NormalizeSteps(buddyTextSteps, buddyTextInfo.Parameters); } // Create unit name UnitName unitName = new UnitName(buddyTextInfo.ApplicationText, buddyTextInfo.VersionText, buddyTextInfo.UseCaseText, buddyTextInfo.ScenarioText); string qualifiedUnitName = unitName.ToQualifiedString(); using (CompilingContext compilingContext = new CompilingContext()) { // Compile directives string[] directiveSet = new string[1000]; int pr = 0; using (StopwatchLog.StartNew(LogInstructionTranslationPerformance)) { for (int i = -1; ++i != normalizedBuddyTextSteps.Length;) { string actionLine = normalizedBuddyTextSteps[i]; string directive = _instructionTranslator.ToDirective(actionLine); directiveSet[pr++] = directive; } Array.Resize(ref directiveSet, pr); } // Add alias references string[] aliasReferenceSet = compilingContext.AliasReferenceSet; tdilFileWriter.AddAlias(aliasReferenceSet); // Add unit references string[] unitReferenceSet = compilingContext.UnitReferenceSet; string[] qualifiedUnitNames = ToQualifiedUnitNames(unitReferenceSet); tdilFileWriter.AddImport(qualifiedUnitNames); // Write unit using (StopwatchLog.StartNew(LogTdilUnitWritingPerformance)) { using (TdilUnitWriter tdilUnitWriter = tdilFileWriter.CreateUnit(qualifiedUnitName)) { string executeSectionName = unitName.GetEncodedScenarioName(); BuddyTextParameter[] unitParameters = buddyTextInfo.Parameters; string[] parameterNames = new string[unitParameters.Length]; for (int l = -1; ++l != parameterNames.Length;) { parameterNames[l] = unitParameters[l].Name; } // Write main section using (TdilSectionWriter tdilSectionWriter = tdilUnitWriter.CreateSection("Main")) { // Declare parameters for (int i = -1; ++i != unitParameters.Length;) { BuddyTextParameter unitParameter = unitParameters[i]; tdilSectionWriter.AppendLine("{0} = {1}", unitParameter.Name, unitParameter.DefaultValue); } // Add start statement tdilSectionWriter.AppendLine("start(,, \"{{{0}}}\")", buddyTextInfo.ApplicationText); // Add argument invocation line if there are some string argInvLine = null; if (parameterNames.Length != 0) { string argSetLine = string.Join(", ", parameterNames); argInvLine = $"({argSetLine})"; } tdilSectionWriter.AppendLine("gosub {0}:{1}", executeSectionName, argInvLine); // Add close statement tdilSectionWriter.AppendLine("close(_Application,, Default)"); tdilSectionWriter.AppendLine("kill(_Application,, 3000)"); tdilSectionWriter.AppendLine("close(\"AcroRd32\",, Default)"); tdilSectionWriter.AppendLine("kill(\"AcroRd32\",, 3000)"); } // Write execute section using (TdilSectionWriter tdilSectionWriter = tdilUnitWriter.CreateSection(executeSectionName, parameterNames)) { for (int l = -1; ++l != directiveSet.Length;) { tdilSectionWriter.AppendLine(directiveSet[l]); } } } } } } catch (BuddyCompilerException) { throw; } catch (Exception ex) { throw new BuddyCompilerException("Error on compiling buddy language unit.", ex); } string tdilFileContent = tdilFileWriter.WriteToString(); compilerStopwatch.Dispose(); return(tdilFileContent); }