diff --git a/YesNt.Interpreter/Attributes/StaticStatementAttribute.cs b/YesNt.Interpreter/Attributes/StaticStatementAttribute.cs index 9b3da5e..28bf029 100644 --- a/YesNt.Interpreter/Attributes/StaticStatementAttribute.cs +++ b/YesNt.Interpreter/Attributes/StaticStatementAttribute.cs @@ -7,7 +7,7 @@ namespace YesNt.Interpreter.Attributes [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] internal class StaticStatementAttribute : Attribute { - public bool ExecuteInSearchLabelMode { get; set; } + public bool ExecuteInSearchMode { get; set; } public Priority Priority { get; set; } = Priority.Normal; } } \ No newline at end of file diff --git a/YesNt.Interpreter/Runtime/RuntimeInformation.cs b/YesNt.Interpreter/Runtime/RuntimeInformation.cs index a8aff17..0339089 100644 --- a/YesNt.Interpreter/Runtime/RuntimeInformation.cs +++ b/YesNt.Interpreter/Runtime/RuntimeInformation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using YesNt.Interpreter.Runtime; using YesNt.Interpreter.Utilities; @@ -11,10 +12,11 @@ namespace YesNt.Interpreter private RuntimeInformation parentRuntimeInformation; private static int internalTaskId = 0; private int taskId = 0; + private readonly Dictionary topVariables = new(); + private readonly Dictionary topLabels = new(); public Dictionary GloablVariables { get; set; } = new(); - public Dictionary Labels { get; } = new(); public Dictionary Functions { get; } = new(); public Stack FunctionCallStack { get; } = new(); public Stack InParametersStack { get; } = new(); @@ -30,8 +32,7 @@ namespace YesNt.Interpreter 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 InternalIsInFunction { get; set; } public bool IsInFunction { @@ -54,6 +55,21 @@ namespace YesNt.Interpreter } } + public Dictionary Labels + { + get + { + if (FunctionCallStack.Count == 0) + { + return topLabels; + } + else + { + return FunctionCallStack.Peek().Labels; + } + } + } + public RuntimeInformation ParentRuntimeInformation { get => parentRuntimeInformation; @@ -68,6 +84,7 @@ namespace YesNt.Interpreter } public bool IsSearching => !string.IsNullOrWhiteSpace(SearchLabel + SearchFunction) || IsInFunction && FunctionCallStack.Count == 0; + public bool IsLocalSearch { get; set; } private event Action OnExit; @@ -75,9 +92,9 @@ namespace YesNt.Interpreter public event Action OnLineExecuted; - private void ParentRuntimeInformation_OnExit(string exitMessage, bool stopChildTasks) + private void ParentRuntimeInformation_OnExit(string exitMessage, bool stopAllTasks) { - Exit($"Terminated by parent task", stopChildTasks); + Exit($"Terminated by parent task", stopAllTasks); } public void WriteLine(string output, bool forceWrite = false) @@ -134,6 +151,13 @@ namespace YesNt.Interpreter { Line line = Lines[Math.Min(LineNumber, Lines.Count - 1)]; WriteLine($"{Environment.NewLine}[{(IsTask ? $"Task {TaskId}" : "The process")} was terminated at line {line.LineNumber + 1} in the file \"{line.FileName}\" with the message: {message}]", true); + while (FunctionCallStack.Count > 0) + { + int stackLineNumber = FunctionCallStack.Pop().CallerLine; + Line stackLine = (ParentRuntimeInformation?.Lines ?? Lines).ElementAt(stackLineNumber); + WriteLine($" at line {stackLine.LineNumber + 1} in the file \"{stackLine.FileName}\"", true); + } + Stop = true; } if (stopAllTasks && !StopAllTasks) @@ -173,7 +197,7 @@ namespace YesNt.Interpreter StopAllTasks = false; IsDebugMode = false; IsInFunction = false; - InternalIsInFunction = false; + IsLocalSearch = false; LineNumber = 0; taskId = internalTaskId + 1; #pragma warning disable S2696 // Instance members should not write to "static" fields diff --git a/YesNt.Interpreter/Statements/CodeFlowStatements.cs b/YesNt.Interpreter/Statements/CodeFlowStatements.cs index 2bd38ae..61bafcf 100644 --- a/YesNt.Interpreter/Statements/CodeFlowStatements.cs +++ b/YesNt.Interpreter/Statements/CodeFlowStatements.cs @@ -23,6 +23,7 @@ namespace YesNt.Interpreter.Statements else { RuntimeInfo.SearchLabel = key; + RuntimeInfo.IsLocalSearch = RuntimeInfo.IsInFunction; } } @@ -59,6 +60,7 @@ namespace YesNt.Interpreter.Statements else { RuntimeInfo.SearchLabel = key; + RuntimeInfo.IsLocalSearch = RuntimeInfo.IsInFunction; } } @@ -78,6 +80,7 @@ namespace YesNt.Interpreter.Statements if (!string.IsNullOrWhiteSpace(RuntimeInfo.SearchLabel) && RuntimeInfo.SearchLabel == key) { RuntimeInfo.SearchLabel = string.Empty; + RuntimeInfo.IsLocalSearch = false; } } @@ -125,7 +128,7 @@ namespace YesNt.Interpreter.Statements return; } - RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack(RuntimeInfo.InParametersStack.Reverse()))); + RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack(RuntimeInfo.InParametersStack))); RuntimeInfo.InParametersStack.Clear(); if (RuntimeInfo.Functions.ContainsKey(key)) @@ -144,6 +147,11 @@ namespace YesNt.Interpreter.Statements if (RuntimeInfo.IsSearching) { RuntimeInfo.IsInFunction = false; + if (RuntimeInfo.IsLocalSearch) + { + RuntimeInfo.Exit($"Label \"{RuntimeInfo.SearchLabel}\" not found", true); + } + return; } else @@ -160,6 +168,11 @@ namespace YesNt.Interpreter.Statements if (RuntimeInfo.IsSearching) { RuntimeInfo.IsInFunction = false; + if (RuntimeInfo.IsLocalSearch) + { + RuntimeInfo.Exit($"Label \"{RuntimeInfo.SearchLabel}\" not found", true); + } + return; } else diff --git a/YesNt.Interpreter/Statements/VariableStatements.cs b/YesNt.Interpreter/Statements/VariableStatements.cs index 5d3232b..b7c3536 100644 --- a/YesNt.Interpreter/Statements/VariableStatements.cs +++ b/YesNt.Interpreter/Statements/VariableStatements.cs @@ -81,8 +81,8 @@ namespace YesNt.Interpreter.Statements } } - [StaticStatement(ExecuteInSearchLabelMode = true)] - public void ReadVariable() + [Statement(">", SearchMode.Contains, SpaceAround.None, Priority = Priority.Highest)] + public void ReadVariable(string _) { if (!RuntimeInfo.CurrentLine.Contains('>')) {