diff --git a/YesNt-Interpreter.sln b/YesNt-Interpreter.sln index 2f72010..29d6502 100644 --- a/YesNt-Interpreter.sln +++ b/YesNt-Interpreter.sln @@ -1,11 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31410.357 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31912.275 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YesNt.Interpreter", "YesNt-Interpreter\YesNt.Interpreter.csproj", "{1D79AC8F-9FC7-4B4C-9899-8DAF2B630030}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YesNt.CodeEditor", "YesNt.CodeEditor\YesNt.CodeEditor.csproj", "{33BDA036-A37E-475E-AACF-8ED96E31BA1A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YesNt.CodeEditor", "YesNt.CodeEditor\YesNt.CodeEditor.csproj", "{33BDA036-A37E-475E-AACF-8ED96E31BA1A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YesNt.Interpreter", "YesNt.Interpreter\YesNt.Interpreter.csproj", "{E40573DB-912A-4871-BB65-3EE6E7D72E79}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,14 +13,14 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1D79AC8F-9FC7-4B4C-9899-8DAF2B630030}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1D79AC8F-9FC7-4B4C-9899-8DAF2B630030}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1D79AC8F-9FC7-4B4C-9899-8DAF2B630030}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1D79AC8F-9FC7-4B4C-9899-8DAF2B630030}.Release|Any CPU.Build.0 = Release|Any CPU {33BDA036-A37E-475E-AACF-8ED96E31BA1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {33BDA036-A37E-475E-AACF-8ED96E31BA1A}.Debug|Any CPU.Build.0 = Debug|Any CPU {33BDA036-A37E-475E-AACF-8ED96E31BA1A}.Release|Any CPU.ActiveCfg = Release|Any CPU {33BDA036-A37E-475E-AACF-8ED96E31BA1A}.Release|Any CPU.Build.0 = Release|Any CPU + {E40573DB-912A-4871-BB65-3EE6E7D72E79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E40573DB-912A-4871-BB65-3EE6E7D72E79}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E40573DB-912A-4871-BB65-3EE6E7D72E79}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E40573DB-912A-4871-BB65-3EE6E7D72E79}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/YesNt-Interpreter/Statements/CodeFlowStatements.cs b/YesNt-Interpreter/Statements/CodeFlowStatements.cs deleted file mode 100644 index b3d0b16..0000000 --- a/YesNt-Interpreter/Statements/CodeFlowStatements.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; - -using YesNt.Interpreter.Attributes; -using YesNt.Interpreter.Enums; -using YesNt.Interpreter.Utilities; - -namespace YesNt.Interpreter.Statements -{ - internal class CodeFlowStatements : StatementRuntimeInformation - { - [Statement("jmp", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, Priority = Priority.VeryLow)] - public void Jump(string args) - { - string key = args.Trim(); - - if (RuntimeInfo.LabelStack.Count == 0 || RuntimeInfo.LabelStack.Peek() != RuntimeInfo.LineNumber) - { - RuntimeInfo.LabelStack.Push(RuntimeInfo.LineNumber); - } - - if (RuntimeInfo.Labels.ContainsKey(key)) - { - RuntimeInfo.LineNumber = RuntimeInfo.Labels[key]; - } - else - { - RuntimeInfo.SearchLabel = key; - } - } - - [Statement("jif", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, Priority = Priority.VeryLow, Seperator = "|")] - 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 != true) - { - if (result is null) - { - RuntimeInfo.Exit("Invalid operation", true); - } - return; - } - - if (RuntimeInfo.LabelStack.Count == 0 || RuntimeInfo.LabelStack.Peek() != RuntimeInfo.LineNumber) - { - RuntimeInfo.LabelStack.Push(RuntimeInfo.LineNumber); - } - - if (RuntimeInfo.Labels.ContainsKey(key)) - { - RuntimeInfo.LineNumber = RuntimeInfo.Labels[key]; - } - else - { - RuntimeInfo.SearchLabel = key; - } - } - - [Statement("lbl", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, ExecuteInSearchLabelMode = 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; - } - } - - [Statement("fnc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, ExecuteInSearchLabelMode = true)] - public void FindFunction(string args) - { - } - - [Statement("ret", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red)] - public void Return(string _) - { - if (RuntimeInfo.LabelStack.Count > 0) - { - RuntimeInfo.LineNumber = RuntimeInfo.LabelStack.Pop(); - } - else - { - RuntimeInfo.Exit("No label in stack", true); - } - } - - [Statement("end", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red)] - public void End(string _) - { - RuntimeInfo.Exit("Planned termination by code", false); - } - - [Statement("trm", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red)] - public void Terminate(string _) - { - RuntimeInfo.Exit("Planned termination by code. Canceling all tasks", true); - } - } -} \ No newline at end of file diff --git a/YesNt.CodeEditor/Editor.cs b/YesNt.CodeEditor/Editor.cs index 870c83c..70b9317 100644 --- a/YesNt.CodeEditor/Editor.cs +++ b/YesNt.CodeEditor/Editor.cs @@ -12,7 +12,7 @@ namespace YesNt.CodeEditor private readonly SyntaxHighlighter syntaxHighlighter; private readonly List debugOutput = new(); - public YesNtInterpreter yesNtInterpreter { get; } = new(); + public YesNtInterpreter YesNtInterpreter { get; } = new(); public int LineOffset { get; set; } = 0; public List Lines { get; } = new(); public Point CursorPosition { get; } = new(0, 0); @@ -29,10 +29,10 @@ namespace YesNt.CodeEditor public TextEditor() { - yesNtInterpreter.Initialize(); - yesNtInterpreter.OnDebugOutput += YesNtInterpreter_OnDebugOutput; - yesNtInterpreter.OnLineExecuted += YesNtInterpreter_OnLineExecuted; - syntaxHighlighter = new(yesNtInterpreter.StatementInformation); + YesNtInterpreter.Initialize(); + YesNtInterpreter.OnDebugOutput += YesNtInterpreter_OnDebugOutput; + YesNtInterpreter.OnLineExecuted += YesNtInterpreter_OnLineExecuted; + syntaxHighlighter = new(YesNtInterpreter.StatementInformation); inputHandler = new InputHandler(this); Console.CancelKeyPress += Console_CancelKeyPress; } @@ -198,7 +198,7 @@ namespace YesNt.CodeEditor Console.ForegroundColor = ConsoleColor.Magenta; string sharedString = (Console.CursorLeft != 0) ? Environment.NewLine : string.Empty; - sharedString += e.IsTask ? $"[Task: {e.TaskId}] " : string.Empty + $"[{e.LineNumber}]"; + sharedString += (e.IsTask ? $"[Task: {e.TaskId}]" : string.Empty) + $"[{e.LineNumber}]"; if (e.OriginalLine == e.CurrentLine) { @@ -226,7 +226,7 @@ namespace YesNt.CodeEditor switch (EditMode) { case Mode.Debug: - yesNtInterpreter.Stop(); + YesNtInterpreter.Stop(); EditMode = Mode.Command; break; } diff --git a/YesNt.CodeEditor/InputHandler.cs b/YesNt.CodeEditor/InputHandler.cs index 3ec8ee6..5edc6c7 100644 --- a/YesNt.CodeEditor/InputHandler.cs +++ b/YesNt.CodeEditor/InputHandler.cs @@ -233,7 +233,7 @@ namespace YesNt.CodeEditor textEditor.EditMode = Mode.Debug; Console.Clear(); Console.CursorVisible = true; - textEditor.yesNtInterpreter.Execute(textEditor.CurrentPath); + textEditor.YesNtInterpreter.Execute(textEditor.CurrentPath); while (Console.KeyAvailable) { Console.ReadKey(true); @@ -250,7 +250,7 @@ namespace YesNt.CodeEditor textEditor.EditMode = Mode.Debug; Console.Clear(); Console.CursorVisible = true; - textEditor.yesNtInterpreter.Execute(textEditor.CurrentPath, true); + textEditor.YesNtInterpreter.Execute(textEditor.CurrentPath, true); while (Console.KeyAvailable) { Console.ReadKey(true); diff --git a/YesNt.CodeEditor/YesNt.CodeEditor.csproj b/YesNt.CodeEditor/YesNt.CodeEditor.csproj index f4ba822..33a02c7 100644 --- a/YesNt.CodeEditor/YesNt.CodeEditor.csproj +++ b/YesNt.CodeEditor/YesNt.CodeEditor.csproj @@ -6,7 +6,7 @@ - + diff --git a/YesNt-Interpreter/Attributes/StatementAttribute.cs b/YesNt.Interpreter/Attributes/StatementAttribute.cs similarity index 95% rename from YesNt-Interpreter/Attributes/StatementAttribute.cs rename to YesNt.Interpreter/Attributes/StatementAttribute.cs index 853224b..9b55c9b 100644 --- a/YesNt-Interpreter/Attributes/StatementAttribute.cs +++ b/YesNt.Interpreter/Attributes/StatementAttribute.cs @@ -12,7 +12,7 @@ namespace YesNt.Interpreter.Attributes public SpaceAround SpaceAround { get; } public ConsoleColor Color { get; set; } public Priority Priority { get; set; } = Priority.Normal; - public bool ExecuteInSearchLabelMode { get; set; } + public bool ExecuteInSearchMode { get; set; } public bool KeepStatementInArgs { get; set; } public bool IgnoreSyntaxHighlighting { get; } public string Seperator { get; set; } diff --git a/YesNt-Interpreter/Attributes/StaticStatementAttribute.cs b/YesNt.Interpreter/Attributes/StaticStatementAttribute.cs similarity index 100% rename from YesNt-Interpreter/Attributes/StaticStatementAttribute.cs rename to YesNt.Interpreter/Attributes/StaticStatementAttribute.cs diff --git a/YesNt-Interpreter/Enums/Priority.cs b/YesNt.Interpreter/Enums/Priority.cs similarity index 100% rename from YesNt-Interpreter/Enums/Priority.cs rename to YesNt.Interpreter/Enums/Priority.cs diff --git a/YesNt-Interpreter/Enums/SearchMode.cs b/YesNt.Interpreter/Enums/SearchMode.cs similarity index 100% rename from YesNt-Interpreter/Enums/SearchMode.cs rename to YesNt.Interpreter/Enums/SearchMode.cs diff --git a/YesNt-Interpreter/Enums/SpaceAround.cs b/YesNt.Interpreter/Enums/SpaceAround.cs similarity index 100% rename from YesNt-Interpreter/Enums/SpaceAround.cs rename to YesNt.Interpreter/Enums/SpaceAround.cs diff --git a/YesNt-Interpreter/Program.cs b/YesNt.Interpreter/Program.cs similarity index 100% rename from YesNt-Interpreter/Program.cs rename to YesNt.Interpreter/Program.cs diff --git a/YesNt-Interpreter/Properties/launchSettings.json b/YesNt.Interpreter/Properties/launchSettings.json similarity index 100% rename from YesNt-Interpreter/Properties/launchSettings.json rename to YesNt.Interpreter/Properties/launchSettings.json diff --git a/YesNt-Interpreter/Runtime/DebugEventArgs.cs b/YesNt.Interpreter/Runtime/DebugEventArgs.cs similarity index 100% rename from YesNt-Interpreter/Runtime/DebugEventArgs.cs rename to YesNt.Interpreter/Runtime/DebugEventArgs.cs diff --git a/YesNt.Interpreter/Runtime/FunctionScope.cs b/YesNt.Interpreter/Runtime/FunctionScope.cs new file mode 100644 index 0000000..8e91f23 --- /dev/null +++ b/YesNt.Interpreter/Runtime/FunctionScope.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace YesNt.Interpreter.Runtime +{ + internal class FunctionScope + { + public int CallerLine { get; } + public Dictionary Variables { get; } = new(); + + public FunctionScope(int callerLine) + { + CallerLine = callerLine; + } + } +} \ No newline at end of file diff --git a/YesNt-Interpreter/Runtime/RuntimeInformation.cs b/YesNt.Interpreter/Runtime/RuntimeInformation.cs similarity index 75% rename from YesNt-Interpreter/Runtime/RuntimeInformation.cs rename to YesNt.Interpreter/Runtime/RuntimeInformation.cs index c5ca149..1447eda 100644 --- a/YesNt-Interpreter/Runtime/RuntimeInformation.cs +++ b/YesNt.Interpreter/Runtime/RuntimeInformation.cs @@ -11,23 +11,47 @@ namespace YesNt.Interpreter private RuntimeInformation parentRuntimeInformation; private static int internalTaskId = 0; private int taskId = 0; + private readonly Dictionary topVariables = new(); - public Dictionary Variables { get; } = new(); public Dictionary GloablVariables { get; set; } = new(); public Dictionary Labels { get; } = new(); + public Dictionary Functions { get; } = new(); + public Stack FunctionCallStack { get; } = new(); public List Lines { get; set; } = new(); public string CurrentLine { get; set; } = string.Empty; - public Stack LabelStack { get; set; } = new(); public string SearchLabel { get; set; } = string.Empty; + public string SearchFunction { get; set; } = string.Empty; public int LineNumber { get; set; } = 0; public bool Stop { get; private set; } = false; public bool StopAllTasks { get; private set; } = false; public bool IsDebugMode { get; set; } = false; public string CurrentFilePath { get; set; } = string.Empty; public bool IsTask => ParentRuntimeInformation is not null; - public int TaskId => IsTask ? taskId : 0; + public bool InternalIsInFunction { get; private set; } = false; + + public bool IsInFunction + { + get => InternalIsInFunction || FunctionCallStack.Count > 0; + set => InternalIsInFunction = value; + } + + public Dictionary Variables + { + get + { + if (FunctionCallStack.Count == 0) + { + return topVariables; + } + else + { + return FunctionCallStack.Peek().Variables; + } + } + } + public RuntimeInformation ParentRuntimeInformation { get => parentRuntimeInformation; @@ -41,6 +65,8 @@ namespace YesNt.Interpreter } } + public bool IsSearching => !string.IsNullOrWhiteSpace(SearchLabel + SearchFunction) || IsInFunction && FunctionCallStack.Count == 0; + private event Action OnExit; public event Action OnDebugOutput; @@ -104,7 +130,7 @@ namespace YesNt.Interpreter { if (!Stop) { - WriteLine($"{Environment.NewLine}[{(IsTask ? "A child task" : "The process")} was terminated at line {LineNumber + 1} with the message: {message}]", true); + WriteLine($"{Environment.NewLine}[{(IsTask ? $"Task: {TaskId}" : "The process")} was terminated at line {LineNumber + 1} with the message: {message}]", true); Stop = true; } if (stopAllTasks == true && StopAllTasks == false) @@ -129,18 +155,22 @@ namespace YesNt.Interpreter public void Reset() { + topVariables.Clear(); Lines.Clear(); - Variables.Clear(); GloablVariables.Clear(); Labels.Clear(); - LabelStack.Clear(); + Functions.Clear(); + FunctionCallStack.Clear(); ParentRuntimeInformation = null; SearchLabel = string.Empty; + SearchFunction = string.Empty; CurrentFilePath = string.Empty; CurrentLine = string.Empty; Stop = false; StopAllTasks = false; IsDebugMode = false; + IsInFunction = false; + InternalIsInFunction = false; LineNumber = 0; taskId = internalTaskId + 1; internalTaskId++; diff --git a/YesNt-Interpreter/Runtime/StatementInformation.cs b/YesNt.Interpreter/Runtime/StatementInformation.cs similarity index 100% rename from YesNt-Interpreter/Runtime/StatementInformation.cs rename to YesNt.Interpreter/Runtime/StatementInformation.cs diff --git a/YesNt-Interpreter/Runtime/StatementRuntimeInfo.cs b/YesNt.Interpreter/Runtime/StatementRuntimeInfo.cs similarity index 100% rename from YesNt-Interpreter/Runtime/StatementRuntimeInfo.cs rename to YesNt.Interpreter/Runtime/StatementRuntimeInfo.cs diff --git a/YesNt-Interpreter/Runtime/YesNtInterpreter.cs b/YesNt.Interpreter/Runtime/YesNtInterpreter.cs similarity index 90% rename from YesNt-Interpreter/Runtime/YesNtInterpreter.cs rename to YesNt.Interpreter/Runtime/YesNtInterpreter.cs index d21830c..b556eba 100644 --- a/YesNt-Interpreter/Runtime/YesNtInterpreter.cs +++ b/YesNt.Interpreter/Runtime/YesNtInterpreter.cs @@ -142,7 +142,7 @@ namespace YesNt.Interpreter foreach (KeyValuePair staticStatement in staticStatements) { StaticStatementAttribute staticStatementAttribute = staticStatement.Key; - if (staticStatementAttribute.ExecuteInSearchLabelMode == false && !string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel)) + if (staticStatementAttribute.ExecuteInSearchLabelMode == false && runtimeInfo.IsSearching) { continue; } @@ -151,13 +151,13 @@ namespace YesNt.Interpreter } bool statementFound = false; - bool searchingLabel = string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel); + bool notSearchingLabel = !runtimeInfo.IsSearching; foreach (KeyValuePair> statement in statements) { StatementAttribute statementAttribute = statement.Key; - if (statementAttribute.ExecuteInSearchLabelMode == false && !string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel)) + if (statementAttribute.ExecuteInSearchMode == false && runtimeInfo.IsSearching) { statementFound = true; continue; @@ -184,10 +184,21 @@ namespace YesNt.Interpreter } else if (statementAttribute.SearchMode == SearchMode.Contains && $" {runtimeInfo.CurrentLine} ".Contains(name)) { + bool leadingWhitespace = runtimeInfo.CurrentLine.StartsWith(' '); + runtimeInfo.CurrentLine = $" {runtimeInfo.CurrentLine} "; string copyLine = statementAttribute.KeepStatementInArgs ? runtimeInfo.CurrentLine : runtimeInfo.CurrentLine.Replace(name, string.Empty); statement.Value.Invoke(copyLine); statementFound = true; + + if (!leadingWhitespace) + { + runtimeInfo.CurrentLine = runtimeInfo.CurrentLine.Trim(); + } + else + { + runtimeInfo.CurrentLine = runtimeInfo.CurrentLine.TrimEnd(); + } } else if (statementAttribute.SearchMode == SearchMode.EndOfLine && runtimeInfo.CurrentLine.EndsWith(name)) { @@ -206,7 +217,7 @@ namespace YesNt.Interpreter { runtimeInfo.Exit("Invalid statement", true); } - if (runtimeInfo.IsDebugMode && searchingLabel) + if (runtimeInfo.IsDebugMode && notSearchingLabel) { debugEventArgs.CurrentLine = runtimeInfo.CurrentLine.FromSaveString(); runtimeInfo.LineExecuted(debugEventArgs); @@ -215,14 +226,19 @@ namespace YesNt.Interpreter if (runtimeInfo.Stop == false) { - if (string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel)) - { - runtimeInfo.Exit("End of file", false); - } - else + if (!string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel)) { runtimeInfo.Exit($"Label \"{runtimeInfo.SearchLabel}\" not found", true); } + else if (!string.IsNullOrWhiteSpace(runtimeInfo.SearchFunction)) + { + runtimeInfo.Exit($"Function \"{runtimeInfo.SearchLabel}\" not found", true); + } + else + { + runtimeInfo.Exit("End of file", false); + } + if (runtimeInfo.IsDebugMode) { runtimeInfo.LineExecuted(null); diff --git a/YesNt.Interpreter/Statements/CodeFlowStatements.cs b/YesNt.Interpreter/Statements/CodeFlowStatements.cs new file mode 100644 index 0000000..bb01e07 --- /dev/null +++ b/YesNt.Interpreter/Statements/CodeFlowStatements.cs @@ -0,0 +1,221 @@ +using System; + +using YesNt.Interpreter.Attributes; +using YesNt.Interpreter.Enums; +using YesNt.Interpreter.Runtime; +using YesNt.Interpreter.Utilities; + +namespace YesNt.Interpreter.Statements +{ + internal class CodeFlowStatements : StatementRuntimeInformation + { + [Statement("jmp", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, Priority = Priority.VeryLow)] + public void Jump(string args) + { + string key = args.Trim(); + + if (RuntimeInfo.Labels.ContainsKey(key)) + { + RuntimeInfo.LineNumber = RuntimeInfo.Labels[key]; + } + else + { + RuntimeInfo.SearchLabel = key; + } + } + + [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)); + + if (RuntimeInfo.Functions.ContainsKey(key)) + { + RuntimeInfo.LineNumber = RuntimeInfo.Functions[key]; + } + else + { + RuntimeInfo.SearchFunction = key; + } + } + + [Statement("jif", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Green, Priority = Priority.VeryLow, Seperator = "|")] + 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 != true) + { + if (result is null) + { + RuntimeInfo.Exit("Invalid operation", true); + } + return; + } + + if (RuntimeInfo.Labels.ContainsKey(key)) + { + RuntimeInfo.LineNumber = RuntimeInfo.Labels[key]; + } + else + { + RuntimeInfo.SearchLabel = 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 != true) + { + if (result is null) + { + RuntimeInfo.Exit("Invalid operation", true); + } + return; + } + + RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber)); + + if (RuntimeInfo.Functions.ContainsKey(key)) + { + RuntimeInfo.LineNumber = RuntimeInfo.Functions[key]; + } + else + { + RuntimeInfo.SearchFunction = key; + } + } + + [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; + } + } + + [Statement("fnc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)] + public void FindFunction(string args) + { + 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; + } + + [Statement("ret", SearchMode.Exact, SpaceAround.None, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)] + public void Return(string _) + { + if (!RuntimeInfo.IsInFunction) + { + RuntimeInfo.Exit("Not in function", true); + return; + } + + if (RuntimeInfo.IsSearching) + { + RuntimeInfo.IsInFunction = false; + return; + } + else + { + RuntimeInfo.IsInFunction = false; + } + + if (RuntimeInfo.FunctionCallStack.Count > 0) + { + RuntimeInfo.LineNumber = RuntimeInfo.FunctionCallStack.Pop().CallerLine; + } + else + { + RuntimeInfo.Exit("No function in stack", true); + } + } + + [Statement("end", SearchMode.Exact, SpaceAround.None, ConsoleColor.Red, ExecuteInSearchMode = true)] + public void End(string _) + { + if (RuntimeInfo.IsSearching) + { + RuntimeInfo.IsInFunction = false; + 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; + return; + } + else + { + RuntimeInfo.IsInFunction = false; + } + + RuntimeInfo.Exit("Planned termination by code. Canceling all tasks", true); + } + } +} \ No newline at end of file diff --git a/YesNt-Interpreter/Statements/ConsoleStatements.cs b/YesNt.Interpreter/Statements/ConsoleStatements.cs similarity index 100% rename from YesNt-Interpreter/Statements/ConsoleStatements.cs rename to YesNt.Interpreter/Statements/ConsoleStatements.cs diff --git a/YesNt-Interpreter/Statements/ProcessingStatements.cs b/YesNt.Interpreter/Statements/ProcessingStatements.cs similarity index 99% rename from YesNt-Interpreter/Statements/ProcessingStatements.cs rename to YesNt.Interpreter/Statements/ProcessingStatements.cs index ef1ccdb..00649f8 100644 --- a/YesNt-Interpreter/Statements/ProcessingStatements.cs +++ b/YesNt.Interpreter/Statements/ProcessingStatements.cs @@ -12,7 +12,7 @@ namespace YesNt.Interpreter.Statements { internal class ProcessingStatements : StatementRuntimeInformation { - [Statement("!calc", SearchMode.EndOfLine, SpaceAround.Start, ConsoleColor.DarkYellow, Priority = Priority.High, ExecuteInSearchLabelMode = true)] + [Statement("!calc", SearchMode.EndOfLine, SpaceAround.Start, ConsoleColor.DarkYellow, Priority = Priority.High, ExecuteInSearchMode = true)] public void Calculate(string args) { MatchCollection matches = Regex.Matches(args, @"((\)?)+(\(?)+[0-9]+(((\s?)+(\)?)(\s?)+\+(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\-(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\*(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\/(\s?)+(\(?)+(\s?)+)|[,.])(?=[0-9])+)+[0-9]+(\)?)+"); diff --git a/YesNt-Interpreter/Statements/VariableStatements.cs b/YesNt.Interpreter/Statements/VariableStatements.cs similarity index 65% rename from YesNt-Interpreter/Statements/VariableStatements.cs rename to YesNt.Interpreter/Statements/VariableStatements.cs index ac9a45e..2fb3f76 100644 --- a/YesNt-Interpreter/Statements/VariableStatements.cs +++ b/YesNt.Interpreter/Statements/VariableStatements.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Text.RegularExpressions; using YesNt.Interpreter.Attributes; using YesNt.Interpreter.Enums; @@ -13,7 +14,7 @@ namespace YesNt.Interpreter.Statements string[] parts = args.Split('='); if (parts.Length == 2) { - string key = parts[0].Replace("<", string.Empty).Trim(); + string key = parts[0].Trim(); if (key.Contains(' ')) { RuntimeInfo.Exit("Invalid Syntax", true); @@ -41,7 +42,7 @@ namespace YesNt.Interpreter.Statements string[] parts = args.Split('='); if (parts.Length == 2) { - string key = parts[0].Replace("!<", string.Empty).Trim(); + string key = parts[0].Trim(); if (key.Contains(' ')) { RuntimeInfo.Exit("Invalid Syntax", true); @@ -63,6 +64,25 @@ namespace YesNt.Interpreter.Statements } } + [Statement("del", SearchMode.StartOfLine, SpaceAround.End, System.ConsoleColor.Red, Priority = Priority.VeryLow)] + public void DeleteVariable(string args) + { + string key = args.Trim(); + + if (RuntimeInfo.Variables.ContainsKey(key)) + { + RuntimeInfo.Variables.Remove(key); + } + else if (RuntimeInfo.GloablVariables.ContainsKey(key)) + { + RuntimeInfo.GloablVariables.Remove(key); + } + else + { + RuntimeInfo.Exit($"Variable \"{key}\" not found", true); + } + } + [StaticStatement(ExecuteInSearchLabelMode = true)] public void ReadVariable() { @@ -80,6 +100,23 @@ namespace YesNt.Interpreter.Statements { RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{variable.Key}", variable.Value); } + + if (RuntimeInfo.IsSearching) + { + return; + } + + MatchCollection matches = Regex.Matches(RuntimeInfo.CurrentLine, @">[a-zA-Z0-9]+"); + + for (int i = 0; i < matches.Count; i++) + { + string varName = matches[i].Value.Replace(">", string.Empty); + if (!RuntimeInfo.Variables.ContainsKey(varName) && !RuntimeInfo.GloablVariables.ContainsKey(varName)) + { + RuntimeInfo.Exit($"Variable \"{varName}\" not found", true); + return; + } + } } } } \ No newline at end of file diff --git a/YesNt-Interpreter/Utilities/ConsoleExtentions.cs b/YesNt.Interpreter/Utilities/ConsoleExtentions.cs similarity index 100% rename from YesNt-Interpreter/Utilities/ConsoleExtentions.cs rename to YesNt.Interpreter/Utilities/ConsoleExtentions.cs diff --git a/YesNt-Interpreter/Utilities/Evaluator.cs b/YesNt.Interpreter/Utilities/Evaluator.cs similarity index 100% rename from YesNt-Interpreter/Utilities/Evaluator.cs rename to YesNt.Interpreter/Utilities/Evaluator.cs diff --git a/YesNt-Interpreter/Utilities/StringExtentions.cs b/YesNt.Interpreter/Utilities/StringExtentions.cs similarity index 100% rename from YesNt-Interpreter/Utilities/StringExtentions.cs rename to YesNt.Interpreter/Utilities/StringExtentions.cs diff --git a/YesNt-Interpreter/YesNt.Interpreter.csproj b/YesNt.Interpreter/YesNt.Interpreter.csproj similarity index 100% rename from YesNt-Interpreter/YesNt.Interpreter.csproj rename to YesNt.Interpreter/YesNt.Interpreter.csproj diff --git a/YesNt-Interpreter/YesNtInterpreter_OLD.cs b/YesNt.Interpreter/YesNtInterpreter_OLD.cs similarity index 100% rename from YesNt-Interpreter/YesNtInterpreter_OLD.cs rename to YesNt.Interpreter/YesNtInterpreter_OLD.cs