From 7078ed5637e99057e24bc1eb72971b93202d95dc Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Wed, 7 Aug 2024 19:44:49 +0200 Subject: [PATCH] Upgrade to .NET 8 and code cleanup --- .editorconfig | 3 + YesNt.CodeEditor/Editor.cs | 16 +- YesNt.CodeEditor/GlobalSuppressions.cs | 2 +- YesNt.CodeEditor/InputHandler.cs | 9 +- .../Properties/launchSettings.json | 18 +- YesNt.CodeEditor/SyntaxHighlighter.cs | 40 +- YesNt.CodeEditor/YesNt.CodeEditor.csproj | 2 +- YesNt.Interpreter.Tests/CodeFowTests.cs | 12 +- .../YesNt.Interpreter.Tests.csproj | 2 +- YesNt.Interpreter.Tests/YesNtAssert.cs | 12 +- .../Attributes/StatementAttribute.cs | 53 +- .../Attributes/StaticStatementAttribute.cs | 13 +- YesNt.Interpreter/Enums/Priority.cs | 21 +- YesNt.Interpreter/Enums/SearchMode.cs | 15 +- YesNt.Interpreter/Enums/SpaceAround.cs | 15 +- YesNt.Interpreter/Program.cs | 25 +- .../Properties/launchSettings.json | 20 +- YesNt.Interpreter/Runtime/DebugEventArgs.cs | 17 +- YesNt.Interpreter/Runtime/FunctionScope.cs | 16 +- YesNt.Interpreter/Runtime/Line.cs | 22 +- .../Runtime/RuntimeInformation.cs | 12 +- .../Runtime/StatementInformation.cs | 19 +- .../Runtime/StatementRuntimeInfo.cs | 9 +- YesNt.Interpreter/Runtime/YesNtInterpreter.cs | 16 +- .../Statements/CodeFlowStatements.cs | 361 ++++++----- .../Statements/FunctionStatements.cs | 345 ++++++----- .../PredifinedVariableStatements.cs | 99 ++- .../Statements/ProcessingStatements.cs | 8 +- .../Statements/SystemStatements.cs | 171 +++--- .../Statements/VariableStatements.cs | 12 +- YesNt.Interpreter/Utilities/FixedProcess.cs | 577 +++++++++--------- .../Utilities/StringExtentions.cs | 4 +- YesNt.Interpreter/YesNt.Interpreter.csproj | 2 +- 33 files changed, 960 insertions(+), 1008 deletions(-) diff --git a/.editorconfig b/.editorconfig index 0ec1ee4..4b19b40 100644 --- a/.editorconfig +++ b/.editorconfig @@ -114,3 +114,6 @@ dotnet_naming_style.pascal_case.required_prefix = dotnet_naming_style.pascal_case.required_suffix = dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case + +# IDE0305: Simplify collection initialization +dotnet_diagnostic.IDE0305.severity = none diff --git a/YesNt.CodeEditor/Editor.cs b/YesNt.CodeEditor/Editor.cs index 7637538..11e1eb5 100644 --- a/YesNt.CodeEditor/Editor.cs +++ b/YesNt.CodeEditor/Editor.cs @@ -11,12 +11,12 @@ internal class TextEditor { private readonly InputHandler inputHandler; private readonly SyntaxHighlighter syntaxHighlighter; - private readonly List debugOutput = new(); + private readonly List debugOutput = []; private readonly Point oldSize = new Point(0, 0); public YesNtInterpreter YesNtInterpreter { get; } = new(); public int LineOffset { get; set; } = 0; - public List Lines { get; } = new(); + public List Lines { get; } = []; public Point CursorPosition { get; } = new(0, 0); public Mode EditMode { get; set; } = Mode.Command; public string CurrentPath { get; set; } = string.Empty; @@ -263,16 +263,10 @@ internal class TextEditor } } -internal class Point +internal class Point(int x, int y) { - public int X { get; set; } - public int Y { get; set; } - - public Point(int x, int y) - { - X = x; - Y = y; - } + public int X { get; set; } = x; + public int Y { get; set; } = y; } internal enum Mode diff --git a/YesNt.CodeEditor/GlobalSuppressions.cs b/YesNt.CodeEditor/GlobalSuppressions.cs index 3e5f094..05f5be2 100644 --- a/YesNt.CodeEditor/GlobalSuppressions.cs +++ b/YesNt.CodeEditor/GlobalSuppressions.cs @@ -5,4 +5,4 @@ using System.Diagnostics.CodeAnalysis; -[assembly: SuppressMessage("Critical Code Smell", "S3998:Threads should not lock on objects with weak identity", Justification = "", Scope = "member", Target = "~M:YesNt.CodeEditor.TextEditor.YesNtInterpreter_OnLineExecuted(YesNt.Interpreter.Runtime.DebugEventArgs)")] +[assembly: SuppressMessage("Critical Code Smell", "S3998:Threads should not lock on objects with weak identity", Justification = "", Scope = "member", Target = "~M:YesNt.CodeEditor.TextEditor.YesNtInterpreter_OnLineExecuted(YesNt.Interpreter.Runtime.DebugEventArgs)")] \ No newline at end of file diff --git a/YesNt.CodeEditor/InputHandler.cs b/YesNt.CodeEditor/InputHandler.cs index 7a6f6b1..924e5b2 100644 --- a/YesNt.CodeEditor/InputHandler.cs +++ b/YesNt.CodeEditor/InputHandler.cs @@ -3,14 +3,9 @@ using System.Text; namespace YesNt.CodeEditor; -internal class InputHandler +internal class InputHandler(TextEditor textEditor) { - private readonly TextEditor textEditor; - - public InputHandler(TextEditor textEditor) - { - this.textEditor = textEditor; - } + private readonly TextEditor textEditor = textEditor; public bool HandleInput() { diff --git a/YesNt.CodeEditor/Properties/launchSettings.json b/YesNt.CodeEditor/Properties/launchSettings.json index 161eba8..d1da8c5 100644 --- a/YesNt.CodeEditor/Properties/launchSettings.json +++ b/YesNt.CodeEditor/Properties/launchSettings.json @@ -1,12 +1,12 @@ { - "profiles": { - "YesNt.CodeEditor": { - "commandName": "Project" - }, - "WSL": { - "commandName": "WSL2", - "environmentVariables": {}, - "distributionName": "" + "profiles": { + "YesNt.CodeEditor": { + "commandName": "Project" + }, + "WSL": { + "commandName": "WSL2", + "environmentVariables": {}, + "distributionName": "" + } } - } } \ No newline at end of file diff --git a/YesNt.CodeEditor/SyntaxHighlighter.cs b/YesNt.CodeEditor/SyntaxHighlighter.cs index 5e8a869..12c664e 100644 --- a/YesNt.CodeEditor/SyntaxHighlighter.cs +++ b/YesNt.CodeEditor/SyntaxHighlighter.cs @@ -9,16 +9,10 @@ using YesNt.Interpreter.Utilities; namespace YesNt.CodeEditor; -internal partial class SyntaxHighlighter +internal partial class SyntaxHighlighter(ReadOnlyCollection statementInformation) { - private readonly ReadOnlyCollection statementInformation; - private readonly string[] replacementValues; - - public SyntaxHighlighter(ReadOnlyCollection statementInformation) - { - this.statementInformation = statementInformation; - replacementValues = StringExtentions.ReplacementRules.Values.ToArray(); - } + private readonly ReadOnlyCollection statementInformation = statementInformation; + private readonly string[] replacementValues = StringExtensions.ReplacementRules.Values.ToArray(); public static string Base64Encode(string plainText) { @@ -64,11 +58,11 @@ internal partial class SyntaxHighlighter input = input.TrimEnd(' '); if (statement.SearchMode == SearchMode.StartOfLine && input.StartsWith(name)) { - if (statement.Seperator is not null && input.Contains(statement.Seperator)) + if (statement.Separator is not null && input.Contains(statement.Separator)) { - input = AddColorInformation(input, statement.Seperator, statement.Color, SearchMode.StartOfLine); + input = AddColorInformation(input, statement.Separator, statement.Color, SearchMode.StartOfLine); } - else if (statement.Seperator is not null) + else if (statement.Separator is not null) { continue; } @@ -76,11 +70,11 @@ internal partial class SyntaxHighlighter } else if (statement.SearchMode == SearchMode.Contains && input.Contains(name)) { - if (statement.Seperator is not null && input.Contains(statement.Seperator)) + if (statement.Separator is not null && input.Contains(statement.Separator)) { - input = AddColorInformation(input, statement.Seperator, statement.Color, SearchMode.StartOfLine); + input = AddColorInformation(input, statement.Separator, statement.Color, SearchMode.StartOfLine); } - else if (statement.Seperator is not null) + else if (statement.Separator is not null) { continue; } @@ -88,11 +82,11 @@ internal partial class SyntaxHighlighter } else if (statement.SearchMode == SearchMode.EndOfLine && input.EndsWith(name)) { - if (statement.Seperator is not null && input.Contains(statement.Seperator)) + if (statement.Separator is not null && input.Contains(statement.Separator)) { - input = AddColorInformation(input, statement.Seperator, statement.Color, SearchMode.StartOfLine); + input = AddColorInformation(input, statement.Separator, statement.Color, SearchMode.StartOfLine); } - else if (statement.Seperator is not null) + else if (statement.Separator is not null) { continue; } @@ -100,11 +94,11 @@ internal partial class SyntaxHighlighter } else if (statement.SearchMode == SearchMode.Exact && input.Equals(name)) { - if (statement.Seperator is not null && input.Contains(statement.Seperator)) + if (statement.Separator is not null && input.Contains(statement.Separator)) { - input = AddColorInformation(input, statement.Seperator, statement.Color, SearchMode.StartOfLine); + input = AddColorInformation(input, statement.Separator, statement.Color, SearchMode.StartOfLine); } - else if (statement.Seperator is not null) + else if (statement.Separator is not null) { continue; } @@ -164,13 +158,13 @@ internal partial class SyntaxHighlighter string base64Value = Base64Encode(value.TrimEnd()); - string reult = searchMode switch + string result = searchMode switch { SearchMode.StartOfLine => originalString.ReplaceFirstOccurrence(value, $"\0\r{(int)color}\r{base64Value}\0" + new string(' ', spacesAtEnd)), SearchMode.EndOfLine => originalString.ReplaceLastOccurrence(value, $"\0\r{(int)color}\r{base64Value}\0" + new string(' ', spacesAtEnd)), _ => originalString.Replace(value, $"\0\r{(int)color}\r{base64Value}\0" + new string(' ', spacesAtEnd)) }; - return reult; + return result; } [GeneratedRegex("^<[a-zA-Z0-9]+")] diff --git a/YesNt.CodeEditor/YesNt.CodeEditor.csproj b/YesNt.CodeEditor/YesNt.CodeEditor.csproj index dd3b5de..b7ba18b 100644 --- a/YesNt.CodeEditor/YesNt.CodeEditor.csproj +++ b/YesNt.CodeEditor/YesNt.CodeEditor.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 AnyCPU;x64 diff --git a/YesNt.Interpreter.Tests/CodeFowTests.cs b/YesNt.Interpreter.Tests/CodeFowTests.cs index 438116b..66444e5 100644 --- a/YesNt.Interpreter.Tests/CodeFowTests.cs +++ b/YesNt.Interpreter.Tests/CodeFowTests.cs @@ -10,28 +10,28 @@ public class CodeFlowTests [TestMethod] public void FunctionTest() { - List lines = new List() - { + List lines = + [ "cal yes", "fnc yes", "!result" - }; + ]; YesNtAssert.IsLastLineEqual(lines, "1"); } [TestMethod] public void LabelsTest() { - List lines = new List() - { + List lines = + [ "result" - }; + ]; YesNtAssert.IsLastLineEqual(lines, "1"); } diff --git a/YesNt.Interpreter.Tests/YesNt.Interpreter.Tests.csproj b/YesNt.Interpreter.Tests/YesNt.Interpreter.Tests.csproj index 5172e5e..3090b90 100644 --- a/YesNt.Interpreter.Tests/YesNt.Interpreter.Tests.csproj +++ b/YesNt.Interpreter.Tests/YesNt.Interpreter.Tests.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable false diff --git a/YesNt.Interpreter.Tests/YesNtAssert.cs b/YesNt.Interpreter.Tests/YesNtAssert.cs index b3aa128..66638d9 100644 --- a/YesNt.Interpreter.Tests/YesNtAssert.cs +++ b/YesNt.Interpreter.Tests/YesNtAssert.cs @@ -42,10 +42,10 @@ internal static class YesNtAssert public static void IsLineEqual(string line, string expected, int timeout = 1000) { AutoResetEvent onDone = new AutoResetEvent(false); - List lines = new List() - { + List lines = + [ line - }; + ]; DebugEventArgs debugEventArgs = new DebugEventArgs(); yesNtInterpreter.OnLineExecuted += (er) => @@ -64,10 +64,10 @@ internal static class YesNtAssert public static void IsLineNotEqual(string line, string expected, int timeout = 1000) { AutoResetEvent onDone = new AutoResetEvent(false); - List lines = new List() - { + List lines = + [ line - }; + ]; DebugEventArgs debugEventArgs = new DebugEventArgs(); yesNtInterpreter.OnLineExecuted += (er) => diff --git a/YesNt.Interpreter/Attributes/StatementAttribute.cs b/YesNt.Interpreter/Attributes/StatementAttribute.cs index 9b55c9b..999c9e8 100644 --- a/YesNt.Interpreter/Attributes/StatementAttribute.cs +++ b/YesNt.Interpreter/Attributes/StatementAttribute.cs @@ -2,35 +2,34 @@ using YesNt.Interpreter.Enums; -namespace YesNt.Interpreter.Attributes +namespace YesNt.Interpreter.Attributes; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] +internal class StatementAttribute : Attribute { - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] - internal class StatementAttribute : Attribute + public string Name { get; } + public SearchMode SearchMode { get; } + public SpaceAround SpaceAround { get; } + public ConsoleColor Color { get; set; } + public Priority Priority { get; set; } = Priority.Normal; + public bool ExecuteInSearchMode { get; set; } + public bool KeepStatementInArgs { get; set; } + public bool IgnoreSyntaxHighlighting { get; } + public string Separator { get; set; } + + internal StatementAttribute(string name, SearchMode searchMode, SpaceAround spaceAround, ConsoleColor color) { - public string Name { get; } - public SearchMode SearchMode { get; } - public SpaceAround SpaceAround { get; } - public ConsoleColor Color { get; set; } - public Priority Priority { get; set; } = Priority.Normal; - public bool ExecuteInSearchMode { get; set; } - public bool KeepStatementInArgs { get; set; } - public bool IgnoreSyntaxHighlighting { get; } - public string Seperator { get; set; } + Name = name; + SearchMode = searchMode; + SpaceAround = spaceAround; + Color = color; + } - internal StatementAttribute(string name, SearchMode searchMode, SpaceAround spaceAround, ConsoleColor color) - { - Name = name; - SearchMode = searchMode; - SpaceAround = spaceAround; - Color = color; - } - - internal StatementAttribute(string name, SearchMode searchMode, SpaceAround spaceAround) - { - Name = name; - SearchMode = searchMode; - SpaceAround = spaceAround; - IgnoreSyntaxHighlighting = true; - } + internal StatementAttribute(string name, SearchMode searchMode, SpaceAround spaceAround) + { + Name = name; + SearchMode = searchMode; + SpaceAround = spaceAround; + IgnoreSyntaxHighlighting = true; } } \ No newline at end of file diff --git a/YesNt.Interpreter/Attributes/StaticStatementAttribute.cs b/YesNt.Interpreter/Attributes/StaticStatementAttribute.cs index 28bf029..f0c5a5a 100644 --- a/YesNt.Interpreter/Attributes/StaticStatementAttribute.cs +++ b/YesNt.Interpreter/Attributes/StaticStatementAttribute.cs @@ -2,12 +2,11 @@ using YesNt.Interpreter.Enums; -namespace YesNt.Interpreter.Attributes +namespace YesNt.Interpreter.Attributes; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] +internal class StaticStatementAttribute : Attribute { - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] - internal class StaticStatementAttribute : Attribute - { - public bool ExecuteInSearchMode { get; set; } - public Priority Priority { get; set; } = Priority.Normal; - } + public bool ExecuteInSearchMode { get; set; } + public Priority Priority { get; set; } = Priority.Normal; } \ No newline at end of file diff --git a/YesNt.Interpreter/Enums/Priority.cs b/YesNt.Interpreter/Enums/Priority.cs index a65051a..acb372b 100644 --- a/YesNt.Interpreter/Enums/Priority.cs +++ b/YesNt.Interpreter/Enums/Priority.cs @@ -1,13 +1,12 @@ -namespace YesNt.Interpreter.Enums +namespace YesNt.Interpreter.Enums; + +internal enum Priority { - internal enum Priority - { - PreProcessing, - Highest, - VeryHigh, - High, - Normal, - Low, - VeryLow - } + PreProcessing, + Highest, + VeryHigh, + High, + Normal, + Low, + VeryLow } \ No newline at end of file diff --git a/YesNt.Interpreter/Enums/SearchMode.cs b/YesNt.Interpreter/Enums/SearchMode.cs index 0e083b8..0226142 100644 --- a/YesNt.Interpreter/Enums/SearchMode.cs +++ b/YesNt.Interpreter/Enums/SearchMode.cs @@ -1,10 +1,9 @@ -namespace YesNt.Interpreter.Enums +namespace YesNt.Interpreter.Enums; + +public enum SearchMode { - public enum SearchMode - { - StartOfLine, - EndOfLine, - Contains, - Exact - } + StartOfLine, + EndOfLine, + Contains, + Exact } \ No newline at end of file diff --git a/YesNt.Interpreter/Enums/SpaceAround.cs b/YesNt.Interpreter/Enums/SpaceAround.cs index c16fd85..0ee0990 100644 --- a/YesNt.Interpreter/Enums/SpaceAround.cs +++ b/YesNt.Interpreter/Enums/SpaceAround.cs @@ -1,10 +1,9 @@ -namespace YesNt.Interpreter.Enums +namespace YesNt.Interpreter.Enums; + +public enum SpaceAround { - public enum SpaceAround - { - StartEnd, - Start, - End, - None - } + StartEnd, + Start, + End, + None } \ No newline at end of file diff --git a/YesNt.Interpreter/Program.cs b/YesNt.Interpreter/Program.cs index 70ce45e..ccbba14 100644 --- a/YesNt.Interpreter/Program.cs +++ b/YesNt.Interpreter/Program.cs @@ -2,22 +2,13 @@ using YesNt.Interpreter.Runtime; -namespace YesNt.Interpreter +if (args.Length == 1) { - internal static class Program - { - private static void Main(string[] args) - { - if (args.Length == 1) - { - YesNtInterpreter interpreter = new YesNtInterpreter(); - interpreter.Initialize(); - interpreter.Execute(args[0]); - } - else - { - Console.WriteLine("No path specified!"); - } - } - } + YesNtInterpreter interpreter = new YesNtInterpreter(); + interpreter.Initialize(); + interpreter.Execute(args[0]); +} +else +{ + Console.WriteLine("No path specified!"); } \ No newline at end of file diff --git a/YesNt.Interpreter/Properties/launchSettings.json b/YesNt.Interpreter/Properties/launchSettings.json index f380490..60b7039 100644 --- a/YesNt.Interpreter/Properties/launchSettings.json +++ b/YesNt.Interpreter/Properties/launchSettings.json @@ -1,13 +1,13 @@ { - "profiles": { - "YesNt-Interpreter": { - "commandName": "Project", - "commandLineArgs": "code.ynt" - }, - "WSL": { - "commandName": "WSL2", - "environmentVariables": {}, - "distributionName": "" + "profiles": { + "YesNt-Interpreter": { + "commandName": "Project", + "commandLineArgs": "code.ynt" + }, + "WSL": { + "commandName": "WSL2", + "environmentVariables": {}, + "distributionName": "" + } } - } } \ No newline at end of file diff --git a/YesNt.Interpreter/Runtime/DebugEventArgs.cs b/YesNt.Interpreter/Runtime/DebugEventArgs.cs index 798d860..0f2d2fe 100644 --- a/YesNt.Interpreter/Runtime/DebugEventArgs.cs +++ b/YesNt.Interpreter/Runtime/DebugEventArgs.cs @@ -1,13 +1,12 @@ using System; -namespace YesNt.Interpreter.Runtime +namespace YesNt.Interpreter.Runtime; + +public class DebugEventArgs : EventArgs { - public class DebugEventArgs : EventArgs - { - public int LineNumber { get; internal set; } - public string CurrentLine { get; internal set; } - public string OriginalLine { get; internal set; } - public int TaskId { get; internal set; } - public bool IsTask { get; internal set; } - } + public int LineNumber { get; internal set; } + public string CurrentLine { get; internal set; } + public string OriginalLine { get; internal set; } + public int TaskId { get; internal set; } + public bool IsTask { get; internal set; } } \ No newline at end of file diff --git a/YesNt.Interpreter/Runtime/FunctionScope.cs b/YesNt.Interpreter/Runtime/FunctionScope.cs index 9b58e0c..cbae505 100644 --- a/YesNt.Interpreter/Runtime/FunctionScope.cs +++ b/YesNt.Interpreter/Runtime/FunctionScope.cs @@ -2,17 +2,11 @@ namespace YesNt.Interpreter.Runtime; -internal class FunctionScope +internal class FunctionScope(int callerLine, Stack arguments) { - public int CallerLine { get; } - public Dictionary Variables { get; } = new(); - public Dictionary Labels { get; } = new(); - public Stack Arguemtns { get; } + public int CallerLine { get; } = callerLine; + public Dictionary Variables { get; } = []; + public Dictionary Labels { get; } = []; + public Stack Arguments { get; } = arguments; public Stack Results { get; } = new(); - - public FunctionScope(int callerLine, Stack arguemtns) - { - CallerLine = callerLine; - Arguemtns = arguemtns; - } } \ No newline at end of file diff --git a/YesNt.Interpreter/Runtime/Line.cs b/YesNt.Interpreter/Runtime/Line.cs index 4243dac..7f3447d 100644 --- a/YesNt.Interpreter/Runtime/Line.cs +++ b/YesNt.Interpreter/Runtime/Line.cs @@ -1,16 +1,10 @@ -namespace YesNt.Interpreter.Runtime -{ - internal class Line - { - public Line(string content, string fileName, int lineNumber) - { - Content = content; - FileName = fileName; - LineNumber = lineNumber; - } +namespace YesNt.Interpreter.Runtime; - public string Content { get; set; } - public string FileName { get; set; } - public int LineNumber { get; set; } - } +internal class Line(string content, string fileName, int lineNumber) +{ + public string Content { get; set; } = content; + + public string FileName { get; set; } = fileName; + + public int LineNumber { get; set; } = lineNumber; } \ No newline at end of file diff --git a/YesNt.Interpreter/Runtime/RuntimeInformation.cs b/YesNt.Interpreter/Runtime/RuntimeInformation.cs index c04e697..0eb4676 100644 --- a/YesNt.Interpreter/Runtime/RuntimeInformation.cs +++ b/YesNt.Interpreter/Runtime/RuntimeInformation.cs @@ -14,16 +14,16 @@ internal sealed class RuntimeInformation private event Action OnExit; private static int internalTaskId = 0; - private readonly Dictionary topVariables = new(); - private readonly Dictionary topLabels = new(); + private readonly Dictionary topVariables = []; + private readonly Dictionary topLabels = []; private RuntimeInformation parentRuntimeInformation; private int taskId = 0; - public Dictionary GloablVariables { get; set; } = new(); - public Dictionary Functions { get; } = new(); + public Dictionary GlobalVariables { get; set; } = []; + public Dictionary Functions { get; } = []; public Stack FunctionCallStack { get; } = new(); public Stack InParametersStack { get; } = new(); public Stack OutParametersStack { get; set; } = new(); - public List Lines { get; set; } = new(); + public List Lines { get; set; } = []; public string CurrentLine { get; set; } = string.Empty; public string SearchLabel { get; set; } = string.Empty; public string SearchFunction { get; set; } = string.Empty; @@ -149,7 +149,7 @@ internal sealed class RuntimeInformation { topVariables.Clear(); Lines.Clear(); - GloablVariables.Clear(); + GlobalVariables.Clear(); Labels.Clear(); Functions.Clear(); FunctionCallStack.Clear(); diff --git a/YesNt.Interpreter/Runtime/StatementInformation.cs b/YesNt.Interpreter/Runtime/StatementInformation.cs index ed9489c..ab7e9a0 100644 --- a/YesNt.Interpreter/Runtime/StatementInformation.cs +++ b/YesNt.Interpreter/Runtime/StatementInformation.cs @@ -2,15 +2,14 @@ using YesNt.Interpreter.Enums; -namespace YesNt.Interpreter.Runtime +namespace YesNt.Interpreter.Runtime; + +public class StatementInformation { - public class StatementInformation - { - public string Name { get; internal set; } - public SearchMode SearchMode { get; internal set; } - public SpaceAround SpaceAround { get; internal set; } - public ConsoleColor Color { get; internal set; } - public bool IgnoreSyntaxHighlighting { get; internal set; } - public string Seperator { get; set; } - } + public string Name { get; internal set; } + public SearchMode SearchMode { get; internal set; } + public SpaceAround SpaceAround { get; internal set; } + public ConsoleColor Color { get; internal set; } + public bool IgnoreSyntaxHighlighting { get; internal set; } + public string Separator { get; set; } } \ No newline at end of file diff --git a/YesNt.Interpreter/Runtime/StatementRuntimeInfo.cs b/YesNt.Interpreter/Runtime/StatementRuntimeInfo.cs index a0aaf2f..3a0c30a 100644 --- a/YesNt.Interpreter/Runtime/StatementRuntimeInfo.cs +++ b/YesNt.Interpreter/Runtime/StatementRuntimeInfo.cs @@ -1,7 +1,6 @@ -namespace YesNt.Interpreter.Runtime +namespace YesNt.Interpreter.Runtime; + +internal abstract class StatementRuntimeInformation { - internal abstract class StatementRuntimeInformation - { - public RuntimeInformation RuntimeInfo { get; set; } - } + public RuntimeInformation RuntimeInfo { get; set; } } \ No newline at end of file diff --git a/YesNt.Interpreter/Runtime/YesNtInterpreter.cs b/YesNt.Interpreter/Runtime/YesNtInterpreter.cs index d11659a..fdfd80d 100644 --- a/YesNt.Interpreter/Runtime/YesNtInterpreter.cs +++ b/YesNt.Interpreter/Runtime/YesNtInterpreter.cs @@ -18,14 +18,14 @@ public class YesNtInterpreter public event Action OnDebugOutput; private readonly RuntimeInformation runtimeInfo = new RuntimeInformation(); - private Dictionary> statements = new(); - private List> staticStatements = new(); + private Dictionary> statements = []; + private List> staticStatements = []; public ReadOnlyCollection StatementInformation { get { - List informations = statements.Select(s => + List information = statements.Select(s => { return new StatementInformation() { @@ -34,11 +34,11 @@ public class YesNtInterpreter SpaceAround = s.Key.SpaceAround, Color = s.Key.Color, IgnoreSyntaxHighlighting = s.Key.IgnoreSyntaxHighlighting, - Seperator = s.Key.Seperator + Separator = s.Key.Separator }; }).ToList(); - return new ReadOnlyCollection(informations); + return new ReadOnlyCollection(information); } } @@ -118,14 +118,14 @@ public class YesNtInterpreter Execute(); } - internal void Execute(List lines, Dictionary gloablVariables, int startLine, RuntimeInformation parentRuntimeInformation) + internal void Execute(List lines, Dictionary globalVariables, int startLine, RuntimeInformation parentRuntimeInformation) { runtimeInfo.Reset(); runtimeInfo.IsDebugMode = parentRuntimeInformation.IsDebugMode; runtimeInfo.Lines = lines; runtimeInfo.LineNumber = startLine; runtimeInfo.ParentRuntimeInformation = parentRuntimeInformation; - runtimeInfo.GloablVariables = gloablVariables; + runtimeInfo.GlobalVariables = globalVariables; if (parentRuntimeInformation.StopAllTasks) { runtimeInfo.Exit($"Parent task was terminated!", parentRuntimeInformation.StopAllTasks); @@ -195,7 +195,7 @@ public class YesNtInterpreter _ => statementAttribute.Name.Trim() }; - if (statementAttribute.Seperator is null || runtimeInfo.CurrentLine.Contains(statementAttribute.Seperator)) + if (statementAttribute.Separator is null || runtimeInfo.CurrentLine.Contains(statementAttribute.Separator)) { if (statementAttribute.SearchMode == SearchMode.StartOfLine && runtimeInfo.CurrentLine.StartsWith(name)) { diff --git a/YesNt.Interpreter/Statements/CodeFlowStatements.cs b/YesNt.Interpreter/Statements/CodeFlowStatements.cs index 61bafcf..d1ccdd6 100644 --- a/YesNt.Interpreter/Statements/CodeFlowStatements.cs +++ b/YesNt.Interpreter/Statements/CodeFlowStatements.cs @@ -7,192 +7,191 @@ using YesNt.Interpreter.Enums; using YesNt.Interpreter.Runtime; using YesNt.Interpreter.Utilities; -namespace YesNt.Interpreter.Statements +namespace YesNt.Interpreter.Statements; + +internal class CodeFlowStatements : StatementRuntimeInformation { - internal class CodeFlowStatements : StatementRuntimeInformation + [Statement("jmp", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, Priority = Priority.VeryLow)] + public void Jump(string args) { - [Statement("jmp", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, Priority = Priority.VeryLow)] - public void Jump(string args) - { - string key = args.Trim(); + string key = args.Trim(); - if (RuntimeInfo.Labels.ContainsKey(key)) - { - RuntimeInfo.LineNumber = RuntimeInfo.Labels[key]; - } - else - { - RuntimeInfo.SearchLabel = key; - RuntimeInfo.IsLocalSearch = RuntimeInfo.IsInFunction; - } + if (RuntimeInfo.Labels.TryGetValue(key, out int value)) + { + RuntimeInfo.LineNumber = value; } - - [Statement("jif", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, Priority = Priority.VeryLow, Seperator = "|")] - public void JumpIf(string args) + else { - string[] parts = args.Split('|'); - if (parts.Length != 2) - { - RuntimeInfo.Exit("Invalid syntax", true); - return; - } - - string key = parts[0].Trim(); - string condition = parts[1].Trim(); - - bool? result = Evaluator.EvaluateCondition(condition); - - if (result is null) - { - RuntimeInfo.Exit("Invalid operation", true); - return; - } - - if (result == false) - { - return; - } - - if (RuntimeInfo.Labels.ContainsKey(key)) - { - RuntimeInfo.LineNumber = RuntimeInfo.Labels[key]; - } - else - { - RuntimeInfo.SearchLabel = key; - RuntimeInfo.IsLocalSearch = RuntimeInfo.IsInFunction; - } - } - - [Statement("lbl", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, ExecuteInSearchMode = true)] - public void FindLabel(string args) - { - string key = args.Trim(); - if (RuntimeInfo.Labels.ContainsKey(key)) - { - RuntimeInfo.Labels[key] = RuntimeInfo.LineNumber; - } - else - { - RuntimeInfo.Labels.Add(key, RuntimeInfo.LineNumber); - } - - if (!string.IsNullOrWhiteSpace(RuntimeInfo.SearchLabel) && RuntimeInfo.SearchLabel == key) - { - RuntimeInfo.SearchLabel = string.Empty; - RuntimeInfo.IsLocalSearch = false; - } - } - - [Statement("cal", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, Priority = Priority.VeryLow)] - public void Call(string args) - { - string key = args.Trim(); - - RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack(RuntimeInfo.InParametersStack.Reverse()))); - RuntimeInfo.InParametersStack.Clear(); - - if (RuntimeInfo.Functions.ContainsKey(key)) - { - RuntimeInfo.LineNumber = RuntimeInfo.Functions[key]; - } - else - { - RuntimeInfo.SearchFunction = key; - } - } - - [Statement("cif", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, Priority = Priority.VeryLow, Seperator = "|")] - public void CallIf(string args) - { - string[] parts = args.Split('|'); - if (parts.Length != 2) - { - RuntimeInfo.Exit("Invalid syntax", true); - return; - } - - string key = parts[0].Trim(); - string condition = parts[1].Trim(); - - bool? result = Evaluator.EvaluateCondition(condition); - - if (result is null) - { - RuntimeInfo.Exit("Invalid operation", true); - return; - } - - if (result == false) - { - return; - } - - RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack(RuntimeInfo.InParametersStack))); - RuntimeInfo.InParametersStack.Clear(); - - if (RuntimeInfo.Functions.ContainsKey(key)) - { - RuntimeInfo.LineNumber = RuntimeInfo.Functions[key]; - } - else - { - RuntimeInfo.SearchFunction = key; - } - } - - [Statement("end", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red, ExecuteInSearchMode = true)] - public void End(string _) - { - if (RuntimeInfo.IsSearching) - { - RuntimeInfo.IsInFunction = false; - if (RuntimeInfo.IsLocalSearch) - { - RuntimeInfo.Exit($"Label \"{RuntimeInfo.SearchLabel}\" not found", true); - } - - return; - } - else - { - RuntimeInfo.IsInFunction = false; - } - - RuntimeInfo.Exit("Planned termination by code", false); - } - - [Statement("trm", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red, ExecuteInSearchMode = true)] - public void Terminate(string _) - { - if (RuntimeInfo.IsSearching) - { - RuntimeInfo.IsInFunction = false; - if (RuntimeInfo.IsLocalSearch) - { - RuntimeInfo.Exit($"Label \"{RuntimeInfo.SearchLabel}\" not found", true); - } - - return; - } - else - { - RuntimeInfo.IsInFunction = false; - } - - RuntimeInfo.Exit("Planned termination by code. Canceling all tasks", true); - } - - [Statement("trw", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Red)] - public void Throw(string message) - { - RuntimeInfo.Exit(message, true); - } - - [Statement("err", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Red)] - public void Error(string message) - { - RuntimeInfo.Exit(message, false); + RuntimeInfo.SearchLabel = key; + RuntimeInfo.IsLocalSearch = RuntimeInfo.IsInFunction; } } + + [Statement("jif", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, Priority = Priority.VeryLow, Separator = "|")] + public void JumpIf(string args) + { + string[] parts = args.Split('|'); + if (parts.Length != 2) + { + RuntimeInfo.Exit("Invalid syntax", true); + return; + } + + string key = parts[0].Trim(); + string condition = parts[1].Trim(); + + bool? result = Evaluator.EvaluateCondition(condition); + + if (result is null) + { + RuntimeInfo.Exit("Invalid operation", true); + return; + } + + if (result == false) + { + return; + } + + if (RuntimeInfo.Labels.TryGetValue(key, out int value)) + { + RuntimeInfo.LineNumber = value; + } + else + { + RuntimeInfo.SearchLabel = key; + RuntimeInfo.IsLocalSearch = RuntimeInfo.IsInFunction; + } + } + + [Statement("lbl", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, ExecuteInSearchMode = true)] + public void FindLabel(string args) + { + string key = args.Trim(); + if (RuntimeInfo.Labels.ContainsKey(key)) + { + RuntimeInfo.Labels[key] = RuntimeInfo.LineNumber; + } + else + { + RuntimeInfo.Labels.Add(key, RuntimeInfo.LineNumber); + } + + if (!string.IsNullOrWhiteSpace(RuntimeInfo.SearchLabel) && RuntimeInfo.SearchLabel == key) + { + RuntimeInfo.SearchLabel = string.Empty; + RuntimeInfo.IsLocalSearch = false; + } + } + + [Statement("cal", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, Priority = Priority.VeryLow)] + public void Call(string args) + { + string key = args.Trim(); + + RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack(RuntimeInfo.InParametersStack.Reverse()))); + RuntimeInfo.InParametersStack.Clear(); + + if (RuntimeInfo.Functions.TryGetValue(key, out int value)) + { + RuntimeInfo.LineNumber = value; + } + else + { + RuntimeInfo.SearchFunction = key; + } + } + + [Statement("cif", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, Priority = Priority.VeryLow, Separator = "|")] + public void CallIf(string args) + { + string[] parts = args.Split('|'); + if (parts.Length != 2) + { + RuntimeInfo.Exit("Invalid syntax", true); + return; + } + + string key = parts[0].Trim(); + string condition = parts[1].Trim(); + + bool? result = Evaluator.EvaluateCondition(condition); + + if (result is null) + { + RuntimeInfo.Exit("Invalid operation", true); + return; + } + + if (result == false) + { + return; + } + + RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack(RuntimeInfo.InParametersStack))); + RuntimeInfo.InParametersStack.Clear(); + + if (RuntimeInfo.Functions.TryGetValue(key, out int value)) + { + RuntimeInfo.LineNumber = value; + } + else + { + RuntimeInfo.SearchFunction = key; + } + } + + [Statement("end", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red, ExecuteInSearchMode = true)] + public void End(string _) + { + if (RuntimeInfo.IsSearching) + { + RuntimeInfo.IsInFunction = false; + if (RuntimeInfo.IsLocalSearch) + { + RuntimeInfo.Exit($"Label \"{RuntimeInfo.SearchLabel}\" not found", true); + } + + return; + } + else + { + RuntimeInfo.IsInFunction = false; + } + + RuntimeInfo.Exit("Planned termination by code", false); + } + + [Statement("trm", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red, ExecuteInSearchMode = true)] + public void Terminate(string _) + { + if (RuntimeInfo.IsSearching) + { + RuntimeInfo.IsInFunction = false; + if (RuntimeInfo.IsLocalSearch) + { + RuntimeInfo.Exit($"Label \"{RuntimeInfo.SearchLabel}\" not found", true); + } + + return; + } + else + { + RuntimeInfo.IsInFunction = false; + } + + RuntimeInfo.Exit("Planned termination by code. Canceling all tasks", true); + } + + [Statement("trw", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Red)] + public void Throw(string message) + { + RuntimeInfo.Exit(message, true); + } + + [Statement("err", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Red)] + public void Error(string message) + { + RuntimeInfo.Exit(message, false); + } } \ No newline at end of file diff --git a/YesNt.Interpreter/Statements/FunctionStatements.cs b/YesNt.Interpreter/Statements/FunctionStatements.cs index 23d67a6..de923c2 100644 --- a/YesNt.Interpreter/Statements/FunctionStatements.cs +++ b/YesNt.Interpreter/Statements/FunctionStatements.cs @@ -5,196 +5,195 @@ using YesNt.Interpreter.Attributes; using YesNt.Interpreter.Enums; using YesNt.Interpreter.Runtime; -namespace YesNt.Interpreter.Statements +namespace YesNt.Interpreter.Statements; + +internal class FunctionStatements : StatementRuntimeInformation { - internal class FunctionStatements : StatementRuntimeInformation + [Statement("fnc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)] + public void FindFunction(string args) { - [Statement("fnc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)] - public void FindFunction(string args) + if (RuntimeInfo.InternalIsInFunction) { - if (RuntimeInfo.InternalIsInFunction) - { - RuntimeInfo.Exit("Nested functions are not allowed", true); - return; - } - - string key = args.Trim(); - if (RuntimeInfo.Functions.ContainsKey(key)) - { - RuntimeInfo.Functions[key] = RuntimeInfo.LineNumber; - } - else - { - RuntimeInfo.Functions.Add(key, RuntimeInfo.LineNumber); - } - - if (!string.IsNullOrWhiteSpace(RuntimeInfo.SearchFunction) && RuntimeInfo.SearchFunction == key) - { - RuntimeInfo.SearchFunction = string.Empty; - } - - RuntimeInfo.IsInFunction = true; + RuntimeInfo.Exit("Nested functions are not allowed", true); + return; } - [Statement("in", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)] - public void AddInParameter(string args) + string key = args.Trim(); + if (RuntimeInfo.Functions.ContainsKey(key)) { - RuntimeInfo.InParametersStack.Push(args); + RuntimeInfo.Functions[key] = RuntimeInfo.LineNumber; + } + else + { + RuntimeInfo.Functions.Add(key, RuntimeInfo.LineNumber); } - [Statement("out", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)] - public void GetOutParameter(string args) + if (!string.IsNullOrWhiteSpace(RuntimeInfo.SearchFunction) && RuntimeInfo.SearchFunction == key) { - if (RuntimeInfo.OutParametersStack.Count == 0) - { - RuntimeInfo.Exit("No out argument in stack", true); - return; - } - - if (RuntimeInfo.Variables.ContainsKey(args)) - { - RuntimeInfo.Variables[args] = RuntimeInfo.OutParametersStack.Pop(); - } - else - { - RuntimeInfo.Variables.Add(args, RuntimeInfo.OutParametersStack.Pop()); - } + RuntimeInfo.SearchFunction = string.Empty; } - [Statement("%iso", SearchMode.Contains, SpaceAround.None, ConsoleColor.Yellow, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void CheckIfOutParameterAvalible(string args) - { - args += " "; - args = args.Replace("%iso", (RuntimeInfo.OutParametersStack.Count > 0).ToString()); + RuntimeInfo.IsInFunction = true; + } - RuntimeInfo.CurrentLine = args.TrimEnd(); + [Statement("in", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)] + public void AddInParameter(string args) + { + RuntimeInfo.InParametersStack.Push(args); + } + + [Statement("out", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)] + public void GetOutParameter(string args) + { + if (RuntimeInfo.OutParametersStack.Count == 0) + { + RuntimeInfo.Exit("No out argument in stack", true); + return; } - [Statement("cal", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, Priority = Priority.Low, Seperator = "|")] - public void Call(string args) + if (RuntimeInfo.Variables.ContainsKey(args)) { - string[] parts = args.Split('|'); - if (parts.Length != 2) - { - RuntimeInfo.Exit("Invalid syntax", true); - return; - } - - string key = parts[0].Trim(); - string[] functionArgumets = parts[1].Split(','); - - foreach (string argumanet in functionArgumets) - { - RuntimeInfo.InParametersStack.Push(argumanet.Trim()); - } - - RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack(RuntimeInfo.InParametersStack))); - RuntimeInfo.InParametersStack.Clear(); - RuntimeInfo.CurrentLine = string.Empty; - - if (RuntimeInfo.Functions.ContainsKey(key)) - { - RuntimeInfo.LineNumber = RuntimeInfo.Functions[key]; - } - else - { - RuntimeInfo.SearchFunction = key; - } + RuntimeInfo.Variables[args] = RuntimeInfo.OutParametersStack.Pop(); } - - [Statement("get", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)] - public void GetInParameter(string args) + else { - if (!RuntimeInfo.IsInFunction) - { - RuntimeInfo.Exit("Statement not allowed outside of function", true); - return; - } - - if (RuntimeInfo.FunctionCallStack.Peek().Arguemtns.Count == 0) - { - RuntimeInfo.Exit("No in argument in stack", true); - return; - } - - if (RuntimeInfo.Variables.ContainsKey(args)) - { - RuntimeInfo.Variables[args] = RuntimeInfo.FunctionCallStack.Peek().Arguemtns.Pop(); - } - else - { - RuntimeInfo.Variables.Add(args, RuntimeInfo.FunctionCallStack.Peek().Arguemtns.Pop()); - } - } - - [Statement("%isi", SearchMode.Contains, SpaceAround.End, ConsoleColor.Yellow, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void CheckIfInParameterAvalible(string args) - { - if (!RuntimeInfo.IsInFunction) - { - RuntimeInfo.Exit("Statement not allowed outside of function", true); - return; - } - - args += " "; - args = args.Replace("%isi", (RuntimeInfo.FunctionCallStack.Peek().Arguemtns.Count > 0).ToString()); - - RuntimeInfo.CurrentLine = args.TrimEnd(); - } - - [Statement("put", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)] - public void AddOutParameter(string args) - { - if (!RuntimeInfo.IsInFunction) - { - RuntimeInfo.Exit("Statement not allowed outside of function", true); - return; - } - - RuntimeInfo.FunctionCallStack.Peek().Results.Push(args); - } - - [Statement("ret", SearchMode.Exact, SpaceAround.None, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)] - public void Return(string _) - { - if (!RuntimeInfo.IsInFunction) - { - RuntimeInfo.Exit("Statement not allowed outside of function", true); - return; - } - - if (RuntimeInfo.IsSearching) - { - RuntimeInfo.IsInFunction = false; - - if (RuntimeInfo.IsLocalSearch) - { - RuntimeInfo.Exit($"Label \"{RuntimeInfo.SearchLabel}\" not found", true); - } - return; - } - else - { - RuntimeInfo.IsInFunction = false; - } - - if (RuntimeInfo.FunctionCallStack.Count > 0) - { - FunctionScope functionScope = RuntimeInfo.FunctionCallStack.Pop(); - - RuntimeInfo.OutParametersStack = new Stack(functionScope.Results); - RuntimeInfo.LineNumber = functionScope.CallerLine; - } - else - { - RuntimeInfo.Exit("No function in stack", true); - } - } - - [Statement("ccs", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red)] - public void ClearCallStack(string _) - { - RuntimeInfo.FunctionCallStack.Clear(); + RuntimeInfo.Variables.Add(args, RuntimeInfo.OutParametersStack.Pop()); } } + + [Statement("%iso", SearchMode.Contains, SpaceAround.None, ConsoleColor.Yellow, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void CheckIfOutParameterAvailable(string args) + { + args += " "; + args = args.Replace("%iso", (RuntimeInfo.OutParametersStack.Count > 0).ToString()); + + RuntimeInfo.CurrentLine = args.TrimEnd(); + } + + [Statement("cal", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, Priority = Priority.Low, Separator = "|")] + public void Call(string args) + { + string[] parts = args.Split('|'); + if (parts.Length != 2) + { + RuntimeInfo.Exit("Invalid syntax", true); + return; + } + + string key = parts[0].Trim(); + string[] functionArguments = parts[1].Split(','); + + foreach (string argument in functionArguments) + { + RuntimeInfo.InParametersStack.Push(argument.Trim()); + } + + RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack(RuntimeInfo.InParametersStack))); + RuntimeInfo.InParametersStack.Clear(); + RuntimeInfo.CurrentLine = string.Empty; + + if (RuntimeInfo.Functions.TryGetValue(key, out int value)) + { + RuntimeInfo.LineNumber = value; + } + else + { + RuntimeInfo.SearchFunction = key; + } + } + + [Statement("get", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)] + public void GetInParameter(string args) + { + if (!RuntimeInfo.IsInFunction) + { + RuntimeInfo.Exit("Statement not allowed outside of function", true); + return; + } + + if (RuntimeInfo.FunctionCallStack.Peek().Arguments.Count == 0) + { + RuntimeInfo.Exit("No in argument in stack", true); + return; + } + + if (RuntimeInfo.Variables.ContainsKey(args)) + { + RuntimeInfo.Variables[args] = RuntimeInfo.FunctionCallStack.Peek().Arguments.Pop(); + } + else + { + RuntimeInfo.Variables.Add(args, RuntimeInfo.FunctionCallStack.Peek().Arguments.Pop()); + } + } + + [Statement("%isi", SearchMode.Contains, SpaceAround.End, ConsoleColor.Yellow, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void CheckIfInParameterAvailable(string args) + { + if (!RuntimeInfo.IsInFunction) + { + RuntimeInfo.Exit("Statement not allowed outside of function", true); + return; + } + + args += " "; + args = args.Replace("%isi", (RuntimeInfo.FunctionCallStack.Peek().Arguments.Count > 0).ToString()); + + RuntimeInfo.CurrentLine = args.TrimEnd(); + } + + [Statement("put", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)] + public void AddOutParameter(string args) + { + if (!RuntimeInfo.IsInFunction) + { + RuntimeInfo.Exit("Statement not allowed outside of function", true); + return; + } + + RuntimeInfo.FunctionCallStack.Peek().Results.Push(args); + } + + [Statement("ret", SearchMode.Exact, SpaceAround.None, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)] + public void Return(string _) + { + if (!RuntimeInfo.IsInFunction) + { + RuntimeInfo.Exit("Statement not allowed outside of function", true); + return; + } + + if (RuntimeInfo.IsSearching) + { + RuntimeInfo.IsInFunction = false; + + if (RuntimeInfo.IsLocalSearch) + { + RuntimeInfo.Exit($"Label \"{RuntimeInfo.SearchLabel}\" not found", true); + } + return; + } + else + { + RuntimeInfo.IsInFunction = false; + } + + if (RuntimeInfo.FunctionCallStack.Count > 0) + { + FunctionScope functionScope = RuntimeInfo.FunctionCallStack.Pop(); + + RuntimeInfo.OutParametersStack = new Stack(functionScope.Results); + RuntimeInfo.LineNumber = functionScope.CallerLine; + } + else + { + RuntimeInfo.Exit("No function in stack", true); + } + } + + [Statement("ccs", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red)] + public void ClearCallStack(string _) + { + RuntimeInfo.FunctionCallStack.Clear(); + } } \ No newline at end of file diff --git a/YesNt.Interpreter/Statements/PredifinedVariableStatements.cs b/YesNt.Interpreter/Statements/PredifinedVariableStatements.cs index 6740f44..e79276f 100644 --- a/YesNt.Interpreter/Statements/PredifinedVariableStatements.cs +++ b/YesNt.Interpreter/Statements/PredifinedVariableStatements.cs @@ -5,61 +5,60 @@ using YesNt.Interpreter.Enums; using YesNt.Interpreter.Runtime; using YesNt.Interpreter.Utilities; -namespace YesNt.Interpreter.Statements +namespace YesNt.Interpreter.Statements; + +internal class PredefinedVariableStatements : StatementRuntimeInformation { - internal class PredifinedVariableStatements : StatementRuntimeInformation + private readonly Random random = new Random(); + + [Statement("%time", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void GetUnixTimestamp(string args) { - private readonly Random random = new Random(); + args = args.Replace("%time", DateTimeOffset.Now.ToUnixTimeSeconds().ToString()); - [Statement("%time", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void GetUnixTimestamp(string args) + RuntimeInfo.CurrentLine = args.TrimEnd(); + } + + [Statement("%os", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void GetOperatingSystem(string args) + { + args = args.Replace("%os", Environment.OSVersion.Platform.ToString()); + + RuntimeInfo.CurrentLine = args.TrimEnd(); + } + + [Statement("%cpu", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void GetProcessorArchitecture(string args) + { + args = args.Replace("%cpu", System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString()); + + RuntimeInfo.CurrentLine = args.TrimEnd(); + } + + [Statement("%is64", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void GetIsOperatingSystem64Bit(string args) + { + args = args.Replace("%is64", $"{Environment.Is64BitOperatingSystem}"); + + RuntimeInfo.CurrentLine = args.TrimEnd(); + } + + [Statement("%pi", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void GetPi(string args) + { + args = args.Replace("%pi", Math.PI.ToString()); + + RuntimeInfo.CurrentLine = args.TrimEnd(); + } + + [Statement("%rnd", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void GetRandom(string args) + { + while (args.Contains("%rnd")) { - args = args.Replace("%time", DateTimeOffset.Now.ToUnixTimeSeconds().ToString()); - - RuntimeInfo.CurrentLine = args.TrimEnd(); + args = args.ReplaceFirstOccurrence("%rnd", random.Next(32767, int.MaxValue).ToString()); } - [Statement("%os", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void GetOperatingSystem(string args) - { - args = args.Replace("%os", Environment.OSVersion.Platform.ToString()); - - RuntimeInfo.CurrentLine = args.TrimEnd(); - } - - [Statement("%cpu", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void GetProcessorArchitecture(string args) - { - args = args.Replace("%cpu", System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString()); - - RuntimeInfo.CurrentLine = args.TrimEnd(); - } - - [Statement("%is64", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void GetIsOperatingSystem64Bit(string args) - { - args = args.Replace("%is64", $"{Environment.Is64BitOperatingSystem}"); - - RuntimeInfo.CurrentLine = args.TrimEnd(); - } - - [Statement("%pi", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void GetPi(string args) - { - args = args.Replace("%pi", Math.PI.ToString()); - - RuntimeInfo.CurrentLine = args.TrimEnd(); - } - - [Statement("%rnd", SearchMode.Contains, SpaceAround.None, ConsoleColor.Blue, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void GetRandom(string args) - { - while (args.Contains("%rnd")) - { - args = args.ReplaceFirstOccurrence("%rnd", random.Next(32767, int.MaxValue).ToString()); - } - - RuntimeInfo.CurrentLine = args.TrimEnd(); - } + RuntimeInfo.CurrentLine = args.TrimEnd(); } } \ No newline at end of file diff --git a/YesNt.Interpreter/Statements/ProcessingStatements.cs b/YesNt.Interpreter/Statements/ProcessingStatements.cs index 54cebf4..e606aea 100644 --- a/YesNt.Interpreter/Statements/ProcessingStatements.cs +++ b/YesNt.Interpreter/Statements/ProcessingStatements.cs @@ -41,17 +41,17 @@ internal partial class ProcessingStatements : StatementRuntimeInformation [Statement("!task", SearchMode.EndOfLine, SpaceAround.Start, ConsoleColor.DarkYellow, Priority = Priority.VeryHigh)] public void RunTask(string line) { - int lineNumer = RuntimeInfo.LineNumber; + int lineNumber = RuntimeInfo.LineNumber; List lines = RuntimeInfo.Lines.GetRange(0, RuntimeInfo.Lines.Count); - Line oldLine = lines[lineNumer]; + Line oldLine = lines[lineNumber]; - lines[lineNumer] = new Line(line, oldLine.FileName, oldLine.LineNumber); + lines[lineNumber] = new Line(line, oldLine.FileName, oldLine.LineNumber); _ = Task.Run(() => { YesNtInterpreter interpreter = new YesNtInterpreter(); interpreter.Initialize(); - interpreter.Execute(lines, RuntimeInfo.GloablVariables, lineNumer, RuntimeInfo); + interpreter.Execute(lines, RuntimeInfo.GlobalVariables, lineNumber, RuntimeInfo); }); RuntimeInfo.CurrentLine = string.Empty; diff --git a/YesNt.Interpreter/Statements/SystemStatements.cs b/YesNt.Interpreter/Statements/SystemStatements.cs index cdf66ec..c8d1e32 100644 --- a/YesNt.Interpreter/Statements/SystemStatements.cs +++ b/YesNt.Interpreter/Statements/SystemStatements.cs @@ -9,105 +9,104 @@ using YesNt.Interpreter.Enums; using YesNt.Interpreter.Runtime; using YesNt.Interpreter.Utilities; -namespace YesNt.Interpreter.Statements +namespace YesNt.Interpreter.Statements; + +internal class SystemStatements : StatementRuntimeInformation { - internal class SystemStatements : StatementRuntimeInformation + [Statement("exc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Magenta, Priority = Priority.Low, Separator = "|")] + public void ExecuteProgramWithArgs(string input) { - [Statement("exc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Magenta, Priority = Priority.Low, Seperator = "|")] - public void ExecuteProgramWithArgs(string input) + string[] parts = input.FromSafeString().Split('|'); + parts[0] = parts[0].Trim(); + + string[] functionArguments = parts[1].Split(','); + + foreach (string argument in functionArguments) { - string[] parts = input.FromSafeString().Split('|'); - parts[0] = parts[0].Trim(); - - string[] functionArgumets = parts[1].Split(','); - - foreach (string argumanet in functionArgumets) - { - RuntimeInfo.InParametersStack.Push(argumanet.Trim()); - } - - try - { - StartProcess(parts[0], string.Join(string.Empty, RuntimeInfo.InParametersStack.Reverse())); - } - catch (FileNotFoundException) - { - RuntimeInfo.Exit($"Cannot find file \"{parts[0]}\".", false); - } - catch (Win32Exception ex) - { - RuntimeInfo.Exit($"Failed to start \"{parts[0]}\". {ex.Message}", false); - } - - //HACK: Clear line to avoid execution from other "exc" statement - RuntimeInfo.CurrentLine = string.Empty; + RuntimeInfo.InParametersStack.Push(argument.Trim()); } - [Statement("exc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Magenta, Priority = Priority.VeryLow)] - public void ExecuteProgram(string input) + try { - try - { - StartProcess(input, string.Join(string.Empty, RuntimeInfo.InParametersStack.Reverse())); - } - catch (FileNotFoundException) - { - RuntimeInfo.Exit($"Cannot find file \"{input}\".", false); - } - catch (Win32Exception ex) - { - RuntimeInfo.Exit($"Failed to start \"{input}\". {ex.Message}", false); - } + StartProcess(parts[0], string.Join(string.Empty, RuntimeInfo.InParametersStack.Reverse())); + } + catch (FileNotFoundException) + { + RuntimeInfo.Exit($"Cannot find file \"{parts[0]}\".", false); + } + catch (Win32Exception ex) + { + RuntimeInfo.Exit($"Failed to start \"{parts[0]}\". {ex.Message}", false); } - private void StartProcess(string name, string args) + //HACK: Clear line to avoid execution from other "exc" statement + RuntimeInfo.CurrentLine = string.Empty; + } + + [Statement("exc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Magenta, Priority = Priority.VeryLow)] + public void ExecuteProgram(string input) + { + try { - RuntimeInfo.OutParametersStack.Clear(); - - FixedProcess process = new FixedProcess - { - StartInfo = new ProcessStartInfo() - { - FileName = name, - Arguments = args, - RedirectStandardOutput = true, - RedirectStandardError = true - } - }; - - process.OutputDataReceived += Process_OutputDataReceived; - process.ErrorDataReceived += Process_ErrorDataReceived; - - _ = process.Start(); - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); - process.WaitForExit(); - - RuntimeInfo.InParametersStack.Clear(); - - RuntimeInfo.OutParametersStack.Push(process.ExitCode.ToString()); + StartProcess(input, string.Join(string.Empty, RuntimeInfo.InParametersStack.Reverse())); } - - private void Process_ErrorDataReceived(object sender, Utilities.DataReceivedEventArgs e) + catch (FileNotFoundException) { - if (string.IsNullOrWhiteSpace(e.Data)) - { - return; - } - - RuntimeInfo.OutParametersStack.Push(e.Data); - Console.Write("Error: " + e.Data); + RuntimeInfo.Exit($"Cannot find file \"{input}\".", false); } - - private void Process_OutputDataReceived(object sender, Utilities.DataReceivedEventArgs e) + catch (Win32Exception ex) { - if (string.IsNullOrWhiteSpace(e.Data)) - { - return; - } - - RuntimeInfo.OutParametersStack.Push(e.Data); - Console.Write(e.Data); + RuntimeInfo.Exit($"Failed to start \"{input}\". {ex.Message}", false); } } + + private void StartProcess(string name, string args) + { + RuntimeInfo.OutParametersStack.Clear(); + + FixedProcess process = new FixedProcess + { + StartInfo = new ProcessStartInfo() + { + FileName = name, + Arguments = args, + RedirectStandardOutput = true, + RedirectStandardError = true + } + }; + + process.OutputDataReceived += Process_OutputDataReceived; + process.ErrorDataReceived += Process_ErrorDataReceived; + + _ = process.Start(); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + process.WaitForExit(); + + RuntimeInfo.InParametersStack.Clear(); + + RuntimeInfo.OutParametersStack.Push(process.ExitCode.ToString()); + } + + private void Process_ErrorDataReceived(object sender, Utilities.DataReceivedEventArgs e) + { + if (string.IsNullOrWhiteSpace(e.Data)) + { + return; + } + + RuntimeInfo.OutParametersStack.Push(e.Data); + Console.Write("Error: " + e.Data); + } + + private void Process_OutputDataReceived(object sender, Utilities.DataReceivedEventArgs e) + { + if (string.IsNullOrWhiteSpace(e.Data)) + { + return; + } + + RuntimeInfo.OutParametersStack.Push(e.Data); + Console.Write(e.Data); + } } \ No newline at end of file diff --git a/YesNt.Interpreter/Statements/VariableStatements.cs b/YesNt.Interpreter/Statements/VariableStatements.cs index 5fd4c5d..dba0c93 100644 --- a/YesNt.Interpreter/Statements/VariableStatements.cs +++ b/YesNt.Interpreter/Statements/VariableStatements.cs @@ -47,13 +47,13 @@ internal partial class VariableStatements : StatementRuntimeInformation RuntimeInfo.Exit("Invalid Syntax", true); } - if (RuntimeInfo.GloablVariables.ContainsKey(key)) + if (RuntimeInfo.GlobalVariables.ContainsKey(key)) { - RuntimeInfo.GloablVariables[key] = parts[1].Trim(); + RuntimeInfo.GlobalVariables[key] = parts[1].Trim(); } else { - RuntimeInfo.GloablVariables.Add(key, parts[1].Trim()); + RuntimeInfo.GlobalVariables.Add(key, parts[1].Trim()); } } else @@ -71,9 +71,9 @@ internal partial class VariableStatements : StatementRuntimeInformation { _ = RuntimeInfo.Variables.Remove(key); } - else if (RuntimeInfo.GloablVariables.ContainsKey(key)) + else if (RuntimeInfo.GlobalVariables.ContainsKey(key)) { - _ = RuntimeInfo.GloablVariables.Remove(key); + _ = RuntimeInfo.GlobalVariables.Remove(key); } else { @@ -103,7 +103,7 @@ internal partial class VariableStatements : StatementRuntimeInformation { RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{varName}", value); } - else if (RuntimeInfo.GloablVariables.TryGetValue(varName, out value)) + else if (RuntimeInfo.GlobalVariables.TryGetValue(varName, out value)) { RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{varName}", value); } diff --git a/YesNt.Interpreter/Utilities/FixedProcess.cs b/YesNt.Interpreter/Utilities/FixedProcess.cs index 46ee530..1117d27 100644 --- a/YesNt.Interpreter/Utilities/FixedProcess.cs +++ b/YesNt.Interpreter/Utilities/FixedProcess.cs @@ -5,312 +5,311 @@ using System.IO; using System.Text; using System.Threading; -namespace YesNt.Interpreter.Utilities +namespace YesNt.Interpreter.Utilities; + +public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e); + +internal delegate void UserCallBack(string data); + +public class FixedProcess : Process { - internal delegate void UserCallBack(string data); + public new event DataReceivedEventHandler OutputDataReceived; - public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e); + public new event DataReceivedEventHandler ErrorDataReceived; - public class FixedProcess : Process + internal AsyncStreamReader output; + internal AsyncStreamReader error; + + public new void BeginOutputReadLine() { - internal AsyncStreamReader output; - internal AsyncStreamReader error; - - public new event DataReceivedEventHandler OutputDataReceived; - - public new event DataReceivedEventHandler ErrorDataReceived; - - public new void BeginOutputReadLine() - { - Stream baseStream = StandardOutput.BaseStream; - output = new AsyncStreamReader(baseStream, new UserCallBack(FixedOutputReadNotifyUser), StandardOutput.CurrentEncoding); - output.BeginReadLine(); - } - - public new void BeginErrorReadLine() - { - Stream baseStream = StandardError.BaseStream; - error = new AsyncStreamReader(baseStream, new UserCallBack(FixedErrorReadNotifyUser), StandardError.CurrentEncoding); - error.BeginReadLine(); - } - - internal void FixedOutputReadNotifyUser(string data) - { - DataReceivedEventHandler outputDataReceived = OutputDataReceived; - if (outputDataReceived != null) - { - DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data); - if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) - { - _ = SynchronizingObject.Invoke(outputDataReceived, new object[] - { - this, - dataReceivedEventArgs - }); - return; - } - outputDataReceived(this, dataReceivedEventArgs); - } - } - - internal void FixedErrorReadNotifyUser(string data) - { - DataReceivedEventHandler errorDataReceived = ErrorDataReceived; - if (errorDataReceived != null) - { - DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data); - if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) - { - _ = SynchronizingObject.Invoke(errorDataReceived, new object[] - { - this, - dataReceivedEventArgs - }); - return; - } - errorDataReceived(this, dataReceivedEventArgs); - } - } + Stream baseStream = StandardOutput.BaseStream; + output = new AsyncStreamReader(baseStream, new UserCallBack(FixedOutputReadNotifyUser), StandardOutput.CurrentEncoding); + output.BeginReadLine(); } - internal class AsyncStreamReader : IDisposable + public new void BeginErrorReadLine() { - internal const int DefaultBufferSize = 1024; - private Stream stream; - private Encoding encoding; - private Decoder decoder; - private byte[] byteBuffer; - private char[] charBuffer; - private UserCallBack userCallBack; - private bool cancelOperation; - private ManualResetEvent eofEvent; - private readonly Queue messageQueue; - private StringBuilder sb; - private bool bLastCarriageReturn; - public virtual Encoding CurrentEncoding => encoding; - public virtual Stream BaseStream => stream; + Stream baseStream = StandardError.BaseStream; + error = new AsyncStreamReader(baseStream, new UserCallBack(FixedErrorReadNotifyUser), StandardError.CurrentEncoding); + error.BeginReadLine(); + } - internal AsyncStreamReader(Stream stream, UserCallBack callback, Encoding encoding) : this(stream, callback, encoding, 1024) + internal void FixedOutputReadNotifyUser(string data) + { + DataReceivedEventHandler outputDataReceived = OutputDataReceived; + if (outputDataReceived != null) { - } - - internal AsyncStreamReader(Stream stream, UserCallBack callback, Encoding encoding, int bufferSize) - { - Init(stream, callback, encoding, bufferSize); - messageQueue = new Queue(); - } - - private void Init(Stream stream, UserCallBack callback, Encoding encoding, int bufferSize) - { - this.stream = stream; - this.encoding = encoding; - userCallBack = callback; - decoder = encoding.GetDecoder(); - if (bufferSize < 128) + DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data); + if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) { - bufferSize = 128; - } - byteBuffer = new byte[bufferSize]; - int _maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize); - charBuffer = new char[_maxCharsPerBuffer]; - cancelOperation = false; - eofEvent = new ManualResetEvent(false); - sb = null; - bLastCarriageReturn = false; - } - - public virtual void Close() - { - Dispose(true); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && stream != null) - { - stream.Close(); - } - if (stream != null) - { - stream = null; - encoding = null; - decoder = null; - byteBuffer = null; - charBuffer = null; - } - if (eofEvent != null) - { - eofEvent.Close(); - eofEvent = null; - } - } - - internal void BeginReadLine() - { - if (cancelOperation) - { - cancelOperation = false; - } - if (sb == null) - { - sb = new StringBuilder(1024); - _ = stream.BeginRead(byteBuffer, 0, byteBuffer.Length, new AsyncCallback(ReadBuffer), null); + _ = SynchronizingObject.Invoke(outputDataReceived, + [ + this, + dataReceivedEventArgs + ]); return; } - FlushMessageQueue(); - } - - internal void CancelOperation() - { - cancelOperation = true; - } - - private void ReadBuffer(IAsyncResult ar) - { - int num; - try - { - num = stream.EndRead(ar); - } - catch (IOException) - { - num = 0; - } - catch (OperationCanceledException) - { - num = 0; - } - if (num == 0) - { - lock (messageQueue) - { - if (sb.Length != 0) - { - messageQueue.Enqueue(sb.ToString()); - sb.Length = 0; - } - messageQueue.Enqueue(null); - } - try - { - FlushMessageQueue(); - return; - } - finally - { - _ = eofEvent.Set(); - } - } - int chars = decoder.GetChars(byteBuffer, 0, num, charBuffer, 0); - _ = sb.Append(charBuffer, 0, chars); - GetLinesFromStringBuilder(); - _ = stream.BeginRead(byteBuffer, 0, byteBuffer.Length, new AsyncCallback(ReadBuffer), null); - } - - private void GetLinesFromStringBuilder() - { - int i = 0; - int num = 0; - int length = sb.Length; - if (bLastCarriageReturn && length > 0 && sb[0] == '\n') - { - i = 1; - num = 1; - bLastCarriageReturn = false; - } - while (i < length) - { - char c = sb[i]; - if (c is '\r' or '\n') - { - if (c == '\r' && i + 1 < length && sb[i + 1] == '\n') - { - i++; - } - - string obj = sb.ToString(num, i + 1 - num); - - num = i + 1; - - lock (messageQueue) - { - messageQueue.Enqueue(obj); - } - } - i++; - } - - // Flush Fix: Send Whatever is left in the buffer - string endOfBuffer = sb.ToString(num, length - num); - lock (messageQueue) - { - messageQueue.Enqueue(endOfBuffer); - num = length; - } - // End Flush Fix - - if (sb[length - 1] == '\r') - { - bLastCarriageReturn = true; - } - if (num < length) - { - _ = sb.Remove(0, num); - } - else - { - sb.Length = 0; - } - FlushMessageQueue(); - } - - private void FlushMessageQueue() - { - while (messageQueue.Count > 0) - { - lock (messageQueue) - { - if (messageQueue.Count > 0) - { - string data = (string)messageQueue.Dequeue(); - if (!cancelOperation) - { - userCallBack(data); - } - } - } - } - } - - internal void WaitUtilEOF() - { - if (eofEvent != null) - { - _ = eofEvent.WaitOne(); - eofEvent.Close(); - eofEvent = null; - } + outputDataReceived(this, dataReceivedEventArgs); } } - public class DataReceivedEventArgs : EventArgs + internal void FixedErrorReadNotifyUser(string data) { - internal string _data; - - /// Gets the line of characters that was written to a redirected output stream. - /// The line that was written by an associated to its redirected or stream. - /// 2 - public string Data => _data; - - internal DataReceivedEventArgs(string data) + DataReceivedEventHandler errorDataReceived = ErrorDataReceived; + if (errorDataReceived != null) { - _data = data; + DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data); + if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) + { + _ = SynchronizingObject.Invoke(errorDataReceived, + [ + this, + dataReceivedEventArgs + ]); + return; + } + errorDataReceived(this, dataReceivedEventArgs); + } + } +} + +public class DataReceivedEventArgs : EventArgs +{ + internal string _data; + + /// Gets the line of characters that was written to a redirected output stream. + /// The line that was written by an associated to its redirected or stream. + /// 2 + public string Data => _data; + + internal DataReceivedEventArgs(string data) + { + _data = data; + } +} + +internal class AsyncStreamReader : IDisposable +{ + internal const int DefaultBufferSize = 1024; + private readonly Queue messageQueue; + private Stream stream; + private Encoding encoding; + private Decoder decoder; + private byte[] byteBuffer; + private char[] charBuffer; + private UserCallBack userCallBack; + private bool cancelOperation; + private ManualResetEvent eofEvent; + private StringBuilder sb; + private bool bLastCarriageReturn; + public virtual Encoding CurrentEncoding => encoding; + public virtual Stream BaseStream => stream; + + internal AsyncStreamReader(Stream stream, UserCallBack callback, Encoding encoding) : this(stream, callback, encoding, 1024) + { + } + + internal AsyncStreamReader(Stream stream, UserCallBack callback, Encoding encoding, int bufferSize) + { + Init(stream, callback, encoding, bufferSize); + messageQueue = new Queue(); + } + + public virtual void Close() + { + Dispose(true); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + internal void BeginReadLine() + { + if (cancelOperation) + { + cancelOperation = false; + } + if (sb == null) + { + sb = new StringBuilder(1024); + _ = stream.BeginRead(byteBuffer, 0, byteBuffer.Length, new AsyncCallback(ReadBuffer), null); + return; + } + FlushMessageQueue(); + } + + internal void CancelOperation() + { + cancelOperation = true; + } + + internal void WaitUtilEOF() + { + if (eofEvent != null) + { + _ = eofEvent.WaitOne(); + eofEvent.Close(); + eofEvent = null; + } + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && stream != null) + { + stream.Close(); + } + if (stream != null) + { + stream = null; + encoding = null; + decoder = null; + byteBuffer = null; + charBuffer = null; + } + if (eofEvent != null) + { + eofEvent.Close(); + eofEvent = null; + } + } + + private void Init(Stream stream, UserCallBack callback, Encoding encoding, int bufferSize) + { + this.stream = stream; + this.encoding = encoding; + userCallBack = callback; + decoder = encoding.GetDecoder(); + if (bufferSize < 128) + { + bufferSize = 128; + } + byteBuffer = new byte[bufferSize]; + int _maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize); + charBuffer = new char[_maxCharsPerBuffer]; + cancelOperation = false; + eofEvent = new ManualResetEvent(false); + sb = null; + bLastCarriageReturn = false; + } + + private void ReadBuffer(IAsyncResult ar) + { + int num; + try + { + num = stream.EndRead(ar); + } + catch (IOException) + { + num = 0; + } + catch (OperationCanceledException) + { + num = 0; + } + if (num == 0) + { + lock (messageQueue) + { + if (sb.Length != 0) + { + messageQueue.Enqueue(sb.ToString()); + sb.Length = 0; + } + messageQueue.Enqueue(null); + } + try + { + FlushMessageQueue(); + return; + } + finally + { + _ = eofEvent.Set(); + } + } + int chars = decoder.GetChars(byteBuffer, 0, num, charBuffer, 0); + _ = sb.Append(charBuffer, 0, chars); + GetLinesFromStringBuilder(); + _ = stream.BeginRead(byteBuffer, 0, byteBuffer.Length, new AsyncCallback(ReadBuffer), null); + } + + private void GetLinesFromStringBuilder() + { + int i = 0; + int num = 0; + int length = sb.Length; + if (bLastCarriageReturn && length > 0 && sb[0] == '\n') + { + i = 1; + num = 1; + bLastCarriageReturn = false; + } + while (i < length) + { + char c = sb[i]; + if (c is '\r' or '\n') + { + if (c == '\r' && i + 1 < length && sb[i + 1] == '\n') + { + i++; + } + + string obj = sb.ToString(num, i + 1 - num); + + num = i + 1; + + lock (messageQueue) + { + messageQueue.Enqueue(obj); + } + } + i++; + } + + // Flush Fix: Send Whatever is left in the buffer + string endOfBuffer = sb.ToString(num, length - num); + lock (messageQueue) + { + messageQueue.Enqueue(endOfBuffer); + num = length; + } + // End Flush Fix + + if (sb[length - 1] == '\r') + { + bLastCarriageReturn = true; + } + if (num < length) + { + _ = sb.Remove(0, num); + } + else + { + sb.Length = 0; + } + FlushMessageQueue(); + } + + private void FlushMessageQueue() + { + while (messageQueue.Count > 0) + { + lock (messageQueue) + { + if (messageQueue.Count > 0) + { + string data = (string)messageQueue.Dequeue(); + if (!cancelOperation) + { + userCallBack(data); + } + } + } } } } \ No newline at end of file diff --git a/YesNt.Interpreter/Utilities/StringExtentions.cs b/YesNt.Interpreter/Utilities/StringExtentions.cs index ca042b8..0feb116 100644 --- a/YesNt.Interpreter/Utilities/StringExtentions.cs +++ b/YesNt.Interpreter/Utilities/StringExtentions.cs @@ -7,7 +7,7 @@ using System.Text; namespace YesNt.Interpreter.Utilities; -public static class StringExtentions +public static class StringExtensions { private static readonly Dictionary reverseReplacementRules; @@ -24,7 +24,7 @@ public static class StringExtentions }; [SuppressMessage("Minor Code Smell", "S3963:\"static\" fields should be initialized inline", Justification = "Doesn't work because it throws a TypeInitializationException")] - static StringExtentions() + static StringExtensions() { reverseReplacementRules = ReplacementRules.ToDictionary(x => x.Value, x => x.Key); } diff --git a/YesNt.Interpreter/YesNt.Interpreter.csproj b/YesNt.Interpreter/YesNt.Interpreter.csproj index 3b71ea2..1093ec0 100644 --- a/YesNt.Interpreter/YesNt.Interpreter.csproj +++ b/YesNt.Interpreter/YesNt.Interpreter.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 YesNt.Interpreter Exe