mirror of
https://github.com/Stone-Red-Code/YesNt-Interpreter.git
synced 2026-09-09 07:56:06 +02:00
Many improvements and bug fixes
This commit is contained in:
@@ -17,6 +17,18 @@ internal partial class SyntaxHighlighter
|
|||||||
this.statementInformation = statementInformation;
|
this.statementInformation = statementInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string Base64Encode(string plainText)
|
||||||
|
{
|
||||||
|
byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
|
||||||
|
return System.Convert.ToBase64String(plainTextBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Base64Decode(string base64EncodedData)
|
||||||
|
{
|
||||||
|
byte[] base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
|
||||||
|
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
|
||||||
|
}
|
||||||
|
|
||||||
public void Write(string input)
|
public void Write(string input)
|
||||||
{
|
{
|
||||||
input = input.Replace("\0", string.Empty);
|
input = input.Replace("\0", string.Empty);
|
||||||
@@ -30,7 +42,7 @@ internal partial class SyntaxHighlighter
|
|||||||
MatchCollection matches = EscapeSequenceRegex().Matches(input);
|
MatchCollection matches = EscapeSequenceRegex().Matches(input);
|
||||||
for (int i = 0; i < matches.Count; i++)
|
for (int i = 0; i < matches.Count; i++)
|
||||||
{
|
{
|
||||||
input = AddColorInformation(input, matches[i].Value, Console.ForegroundColor, SearchMode.Contains);
|
input = AddColorInformation(input, matches[i].Value, ConsoleColor.DarkYellow, SearchMode.Contains);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (StatementInformation statement in statementInformation)
|
foreach (StatementInformation statement in statementInformation)
|
||||||
@@ -45,9 +57,9 @@ internal partial class SyntaxHighlighter
|
|||||||
SpaceAround.StartEnd => $" {statement.Name.Trim()} ",
|
SpaceAround.StartEnd => $" {statement.Name.Trim()} ",
|
||||||
SpaceAround.Start => $" {statement.Name.Trim()}",
|
SpaceAround.Start => $" {statement.Name.Trim()}",
|
||||||
SpaceAround.End => $"{statement.Name.Trim()} ",
|
SpaceAround.End => $"{statement.Name.Trim()} ",
|
||||||
_ => statement.Name
|
_ => statement.Name.Trim()
|
||||||
};
|
};
|
||||||
input = input.TrimEnd();
|
input = input.TrimEnd(' ');
|
||||||
if (statement.SearchMode == SearchMode.StartOfLine && input.StartsWith(name))
|
if (statement.SearchMode == SearchMode.StartOfLine && input.StartsWith(name))
|
||||||
{
|
{
|
||||||
if (statement.Seperator is not null && input.Contains(statement.Seperator))
|
if (statement.Seperator is not null && input.Contains(statement.Seperator))
|
||||||
@@ -60,7 +72,7 @@ internal partial class SyntaxHighlighter
|
|||||||
}
|
}
|
||||||
input = AddColorInformation(input, input[..name.Length], statement.Color, statement.SearchMode);
|
input = AddColorInformation(input, input[..name.Length], statement.Color, statement.SearchMode);
|
||||||
}
|
}
|
||||||
if (statement.SearchMode == SearchMode.Contains && $" {input} ".Contains(name))
|
else if (statement.SearchMode == SearchMode.Contains && input.Contains(name))
|
||||||
{
|
{
|
||||||
if (statement.Seperator is not null && input.Contains(statement.Seperator))
|
if (statement.Seperator is not null && input.Contains(statement.Seperator))
|
||||||
{
|
{
|
||||||
@@ -70,9 +82,9 @@ internal partial class SyntaxHighlighter
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
input = AddColorInformation($"{input} ", $"{input} ".Substring($"{input} ".IndexOf(name), name.Length), statement.Color, statement.SearchMode);
|
input = AddColorInformation(input, input.Substring(input.IndexOf(name), name.Length), statement.Color, statement.SearchMode);
|
||||||
}
|
}
|
||||||
if (statement.SearchMode == SearchMode.EndOfLine && input.EndsWith(name))
|
else if (statement.SearchMode == SearchMode.EndOfLine && input.EndsWith(name))
|
||||||
{
|
{
|
||||||
if (statement.Seperator is not null && input.Contains(statement.Seperator))
|
if (statement.Seperator is not null && input.Contains(statement.Seperator))
|
||||||
{
|
{
|
||||||
@@ -84,7 +96,7 @@ internal partial class SyntaxHighlighter
|
|||||||
}
|
}
|
||||||
input = AddColorInformation(input, input[^name.Length..], statement.Color, statement.SearchMode);
|
input = AddColorInformation(input, input[^name.Length..], statement.Color, statement.SearchMode);
|
||||||
}
|
}
|
||||||
if (statement.SearchMode == SearchMode.Exact && input.Equals(name))
|
else if (statement.SearchMode == SearchMode.Exact && input.Equals(name))
|
||||||
{
|
{
|
||||||
if (statement.Seperator is not null && input.Contains(statement.Seperator))
|
if (statement.Seperator is not null && input.Contains(statement.Seperator))
|
||||||
{
|
{
|
||||||
@@ -126,7 +138,7 @@ internal partial class SyntaxHighlighter
|
|||||||
bool succ = int.TryParse(stringColor, out int colorIndex);
|
bool succ = int.TryParse(stringColor, out int colorIndex);
|
||||||
if (succ && colorIndex >= 0 && colorIndex < 16)
|
if (succ && colorIndex >= 0 && colorIndex < 16)
|
||||||
{
|
{
|
||||||
messagePart = messagePart.Replace($"\r{stringColor}\r", string.Empty);
|
messagePart = Base64Decode(messagePart.Replace($"\r{stringColor}\r", string.Empty));
|
||||||
consoleColor = (ConsoleColor)colorIndex;
|
consoleColor = (ConsoleColor)colorIndex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -147,11 +159,14 @@ internal partial class SyntaxHighlighter
|
|||||||
private static string AddColorInformation(string originalString, string value, ConsoleColor color, SearchMode searchMode)
|
private static string AddColorInformation(string originalString, string value, ConsoleColor color, SearchMode searchMode)
|
||||||
{
|
{
|
||||||
int spacesAtEnd = value.WhiteSpaceAtEnd();
|
int spacesAtEnd = value.WhiteSpaceAtEnd();
|
||||||
|
|
||||||
|
string base64Value = Base64Encode(value.TrimEnd());
|
||||||
|
|
||||||
string reult = searchMode switch
|
string reult = searchMode switch
|
||||||
{
|
{
|
||||||
SearchMode.StartOfLine => originalString.ReplaceFirstOccurrence(value, $"\0\r{(int)color}\r{value.TrimEnd()}\0" + new string(' ', spacesAtEnd)),
|
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{value.TrimEnd()}\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{value.TrimEnd()}\0" + new string(' ', spacesAtEnd))
|
_ => originalString.Replace(value, $"\0\r{(int)color}\r{base64Value}\0" + new string(' ', spacesAtEnd))
|
||||||
};
|
};
|
||||||
return reult;
|
return reult;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace YesNt.Interpreter.Runtime
|
namespace YesNt.Interpreter.Runtime;
|
||||||
{
|
|
||||||
internal class FunctionScope
|
|
||||||
{
|
|
||||||
public int CallerLine { get; }
|
|
||||||
public Dictionary<string, string> Variables { get; } = new();
|
|
||||||
public Dictionary<string, int> Labels { get; } = new();
|
|
||||||
public Stack<string> Arguemtns { get; }
|
|
||||||
public Stack<string> Results { get; } = new();
|
|
||||||
|
|
||||||
public FunctionScope(int callerLine, Stack<string> arguemtns)
|
internal class FunctionScope
|
||||||
{
|
{
|
||||||
CallerLine = callerLine;
|
public int CallerLine { get; }
|
||||||
Arguemtns = arguemtns;
|
public Dictionary<string, string> Variables { get; } = new();
|
||||||
}
|
public Dictionary<string, int> Labels { get; } = new();
|
||||||
|
public Stack<string> Arguemtns { get; }
|
||||||
|
public Stack<string> Results { get; } = new();
|
||||||
|
|
||||||
|
public FunctionScope(int callerLine, Stack<string> arguemtns)
|
||||||
|
{
|
||||||
|
CallerLine = callerLine;
|
||||||
|
Arguemtns = arguemtns;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,181 +1,177 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
using YesNt.Interpreter.Utilities;
|
using YesNt.Interpreter.Utilities;
|
||||||
|
|
||||||
namespace YesNt.Interpreter.Runtime
|
namespace YesNt.Interpreter.Runtime;
|
||||||
|
|
||||||
|
internal sealed class RuntimeInformation
|
||||||
{
|
{
|
||||||
internal sealed class RuntimeInformation
|
public event Action<string> OnDebugOutput;
|
||||||
|
|
||||||
|
public event Action<DebugEventArgs> OnLineExecuted;
|
||||||
|
|
||||||
|
private event Action<string, bool> OnExit;
|
||||||
|
|
||||||
|
private static int internalTaskId = 0;
|
||||||
|
private readonly Dictionary<string, string> topVariables = new();
|
||||||
|
private readonly Dictionary<string, int> topLabels = new();
|
||||||
|
private RuntimeInformation parentRuntimeInformation;
|
||||||
|
private int taskId = 0;
|
||||||
|
public Dictionary<string, string> GloablVariables { get; set; } = new();
|
||||||
|
public Dictionary<string, int> Functions { get; } = new();
|
||||||
|
public Stack<FunctionScope> FunctionCallStack { get; } = new();
|
||||||
|
public Stack<string> InParametersStack { get; } = new();
|
||||||
|
public Stack<string> OutParametersStack { get; set; } = new();
|
||||||
|
public List<Line> Lines { get; set; } = new();
|
||||||
|
public string CurrentLine { get; set; } = string.Empty;
|
||||||
|
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 WorkingDirectory { get; set; } = string.Empty;
|
||||||
|
public bool IsTask => ParentRuntimeInformation is not null;
|
||||||
|
public int TaskId => IsTask ? taskId : 0;
|
||||||
|
public bool InternalIsInFunction { get; set; }
|
||||||
|
|
||||||
|
public bool IsInFunction
|
||||||
{
|
{
|
||||||
private RuntimeInformation parentRuntimeInformation;
|
get => InternalIsInFunction || FunctionCallStack.Count > 0;
|
||||||
private static int internalTaskId = 0;
|
set => InternalIsInFunction = value;
|
||||||
private int taskId = 0;
|
}
|
||||||
|
|
||||||
private readonly Dictionary<string, string> topVariables = new();
|
public Dictionary<string, string> Variables => FunctionCallStack.Count == 0 ? topVariables : FunctionCallStack.Peek().Variables;
|
||||||
private readonly Dictionary<string, int> topLabels = new();
|
|
||||||
|
|
||||||
public Dictionary<string, string> GloablVariables { get; set; } = new();
|
public Dictionary<string, int> Labels => FunctionCallStack.Count == 0 ? topLabels : FunctionCallStack.Peek().Labels;
|
||||||
public Dictionary<string, int> Functions { get; } = new();
|
|
||||||
public Stack<FunctionScope> FunctionCallStack { get; } = new();
|
|
||||||
public Stack<string> InParametersStack { get; } = new();
|
|
||||||
public Stack<string> OutParametersStack { get; set; } = new();
|
|
||||||
public List<Line> Lines { get; set; } = new();
|
|
||||||
public string CurrentLine { get; set; } = string.Empty;
|
|
||||||
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 WorkingDirectory { get; set; } = string.Empty;
|
|
||||||
public bool IsTask => ParentRuntimeInformation is not null;
|
|
||||||
public int TaskId => IsTask ? taskId : 0;
|
|
||||||
public bool InternalIsInFunction { get; set; }
|
|
||||||
|
|
||||||
public bool IsInFunction
|
public RuntimeInformation ParentRuntimeInformation
|
||||||
|
{
|
||||||
|
get => parentRuntimeInformation;
|
||||||
|
set
|
||||||
{
|
{
|
||||||
get => InternalIsInFunction || FunctionCallStack.Count > 0;
|
parentRuntimeInformation = value;
|
||||||
set => InternalIsInFunction = value;
|
if (parentRuntimeInformation is not null)
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<string, string> Variables => FunctionCallStack.Count == 0 ? topVariables : FunctionCallStack.Peek().Variables;
|
|
||||||
|
|
||||||
public Dictionary<string, int> Labels => FunctionCallStack.Count == 0 ? topLabels : FunctionCallStack.Peek().Labels;
|
|
||||||
|
|
||||||
public RuntimeInformation ParentRuntimeInformation
|
|
||||||
{
|
|
||||||
get => parentRuntimeInformation;
|
|
||||||
set
|
|
||||||
{
|
{
|
||||||
parentRuntimeInformation = value;
|
parentRuntimeInformation.OnExit += ParentRuntimeInformation_OnExit;
|
||||||
if (parentRuntimeInformation is not null)
|
|
||||||
{
|
|
||||||
parentRuntimeInformation.OnExit += ParentRuntimeInformation_OnExit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsSearching => !string.IsNullOrWhiteSpace(SearchLabel + SearchFunction) || (IsInFunction && FunctionCallStack.Count == 0);
|
public bool IsSearching => !string.IsNullOrWhiteSpace(SearchLabel + SearchFunction) || (IsInFunction && FunctionCallStack.Count == 0);
|
||||||
public bool IsLocalSearch { get; set; }
|
public bool IsLocalSearch { get; set; }
|
||||||
|
|
||||||
private event Action<string, bool> OnExit;
|
public void WriteLine(string output, bool forceWrite = false)
|
||||||
|
{
|
||||||
public event Action<string> OnDebugOutput;
|
if ((Stop && !forceWrite) || (parentRuntimeInformation?.StopAllTasks == true && !forceWrite))
|
||||||
|
|
||||||
public event Action<DebugEventArgs> OnLineExecuted;
|
|
||||||
|
|
||||||
private void ParentRuntimeInformation_OnExit(string exitMessage, bool stopAllTasks)
|
|
||||||
{
|
{
|
||||||
Exit($"Terminated by parent task", stopAllTasks);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteLine(string output, bool forceWrite = false)
|
if (IsDebugMode)
|
||||||
{
|
|
||||||
if ((Stop && !forceWrite) || (parentRuntimeInformation?.StopAllTasks == true && !forceWrite))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsDebugMode)
|
|
||||||
{
|
|
||||||
if (IsTask)
|
|
||||||
{
|
|
||||||
parentRuntimeInformation!.WriteLine(output.FromSafeString(), forceWrite);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OnDebugOutput?.Invoke(output.FromSafeString() + Environment.NewLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine(output.FromSafeString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(string output, bool forceWrite = false)
|
|
||||||
{
|
|
||||||
if ((Stop && !forceWrite) || (parentRuntimeInformation?.StopAllTasks == true && !forceWrite))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsDebugMode)
|
|
||||||
{
|
|
||||||
if (IsTask)
|
|
||||||
{
|
|
||||||
parentRuntimeInformation!.Write(output.FromSafeString(), forceWrite);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OnDebugOutput?.Invoke(output.FromSafeString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.Write(output.FromSafeString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Exit(string message, bool stopAllTasks)
|
|
||||||
{
|
|
||||||
if (!Stop)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
StopAllTasks = true;
|
|
||||||
OnExit?.Invoke(message, StopAllTasks);
|
|
||||||
parentRuntimeInformation?.Exit("Terminated by child task", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LineExecuted(DebugEventArgs debugEventArgs)
|
|
||||||
{
|
{
|
||||||
if (IsTask)
|
if (IsTask)
|
||||||
{
|
{
|
||||||
parentRuntimeInformation.LineExecuted(debugEventArgs);
|
parentRuntimeInformation!.WriteLine(output.FromSafeString(), forceWrite);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OnLineExecuted?.Invoke(debugEventArgs);
|
OnDebugOutput?.Invoke(output.FromSafeString() + Environment.NewLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
public void Reset()
|
|
||||||
{
|
{
|
||||||
topVariables.Clear();
|
Console.WriteLine(output.FromSafeString());
|
||||||
Lines.Clear();
|
|
||||||
GloablVariables.Clear();
|
|
||||||
Labels.Clear();
|
|
||||||
Functions.Clear();
|
|
||||||
FunctionCallStack.Clear();
|
|
||||||
ParentRuntimeInformation = null;
|
|
||||||
SearchLabel = string.Empty;
|
|
||||||
SearchFunction = string.Empty;
|
|
||||||
WorkingDirectory = string.Empty;
|
|
||||||
CurrentLine = string.Empty;
|
|
||||||
Stop = false;
|
|
||||||
StopAllTasks = false;
|
|
||||||
IsDebugMode = false;
|
|
||||||
IsInFunction = false;
|
|
||||||
IsLocalSearch = false;
|
|
||||||
LineNumber = 0;
|
|
||||||
taskId = internalTaskId + 1;
|
|
||||||
#pragma warning disable S2696 // Instance members should not write to "static" fields
|
|
||||||
internalTaskId++;
|
|
||||||
#pragma warning restore S2696 // Instance members should not write to "static" fields
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Write(string output, bool forceWrite = false)
|
||||||
|
{
|
||||||
|
if ((Stop && !forceWrite) || (parentRuntimeInformation?.StopAllTasks == true && !forceWrite))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDebugMode)
|
||||||
|
{
|
||||||
|
if (IsTask)
|
||||||
|
{
|
||||||
|
parentRuntimeInformation!.Write(output.FromSafeString(), forceWrite);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnDebugOutput?.Invoke(output.FromSafeString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.Write(output.FromSafeString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Exit(string message, bool stopAllTasks)
|
||||||
|
{
|
||||||
|
if (!Stop)
|
||||||
|
{
|
||||||
|
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)[stackLineNumber];
|
||||||
|
WriteLine($" at line {stackLine.LineNumber + 1} in the file \"{stackLine.FileName}\"", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stop = true;
|
||||||
|
}
|
||||||
|
if (stopAllTasks && !StopAllTasks)
|
||||||
|
{
|
||||||
|
StopAllTasks = true;
|
||||||
|
OnExit?.Invoke(message, StopAllTasks);
|
||||||
|
parentRuntimeInformation?.Exit("Terminated by child task", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LineExecuted(DebugEventArgs debugEventArgs)
|
||||||
|
{
|
||||||
|
if (IsTask)
|
||||||
|
{
|
||||||
|
parentRuntimeInformation.LineExecuted(debugEventArgs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnLineExecuted?.Invoke(debugEventArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
topVariables.Clear();
|
||||||
|
Lines.Clear();
|
||||||
|
GloablVariables.Clear();
|
||||||
|
Labels.Clear();
|
||||||
|
Functions.Clear();
|
||||||
|
FunctionCallStack.Clear();
|
||||||
|
ParentRuntimeInformation = null;
|
||||||
|
SearchLabel = string.Empty;
|
||||||
|
SearchFunction = string.Empty;
|
||||||
|
WorkingDirectory = string.Empty;
|
||||||
|
CurrentLine = string.Empty;
|
||||||
|
Stop = false;
|
||||||
|
StopAllTasks = false;
|
||||||
|
IsDebugMode = false;
|
||||||
|
IsInFunction = false;
|
||||||
|
IsLocalSearch = false;
|
||||||
|
LineNumber = 0;
|
||||||
|
taskId = internalTaskId + 1;
|
||||||
|
#pragma warning disable S2696 // Instance members should not write to "static" fields
|
||||||
|
internalTaskId++;
|
||||||
|
#pragma warning restore S2696 // Instance members should not write to "static" fields
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParentRuntimeInformation_OnExit(string exitMessage, bool stopAllTasks)
|
||||||
|
{
|
||||||
|
Exit($"Terminated by parent task", stopAllTasks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,10 @@ namespace YesNt.Interpreter.Runtime;
|
|||||||
|
|
||||||
public class YesNtInterpreter
|
public class YesNtInterpreter
|
||||||
{
|
{
|
||||||
|
public event Action<DebugEventArgs> OnLineExecuted;
|
||||||
|
|
||||||
|
public event Action<string> OnDebugOutput;
|
||||||
|
|
||||||
private readonly RuntimeInformation runtimeInfo = new RuntimeInformation();
|
private readonly RuntimeInformation runtimeInfo = new RuntimeInformation();
|
||||||
private Dictionary<StatementAttribute, Action<string>> statements = new();
|
private Dictionary<StatementAttribute, Action<string>> statements = new();
|
||||||
private List<KeyValuePair<StaticStatementAttribute, Action>> staticStatements = new();
|
private List<KeyValuePair<StaticStatementAttribute, Action>> staticStatements = new();
|
||||||
@@ -38,10 +42,6 @@ public class YesNtInterpreter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Action<DebugEventArgs> OnLineExecuted;
|
|
||||||
|
|
||||||
public event Action<string> OnDebugOutput;
|
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
runtimeInfo.Exit("Terminated by external process", true);
|
runtimeInfo.Exit("Terminated by external process", true);
|
||||||
@@ -83,8 +83,13 @@ public class YesNtInterpreter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
statements = statements.OrderBy(s => s.Key.Priority).ToDictionary(x => x.Key, x => x.Value);
|
statements = statements
|
||||||
staticStatements = staticStatements.OrderBy(s => s.Key.Priority).ToList();
|
.OrderBy(s => s.Key.Priority)
|
||||||
|
.ThenByDescending(s => s.Key.Name.Length)
|
||||||
|
.ToDictionary(x => x.Key, x => x.Value);
|
||||||
|
staticStatements = staticStatements
|
||||||
|
.OrderBy(s => s.Key.Priority)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
runtimeInfo.OnDebugOutput += (s) => OnDebugOutput?.Invoke(s);
|
runtimeInfo.OnDebugOutput += (s) => OnDebugOutput?.Invoke(s);
|
||||||
runtimeInfo.OnLineExecuted += (DebugEventArgs e) => OnLineExecuted?.Invoke(e);
|
runtimeInfo.OnLineExecuted += (DebugEventArgs e) => OnLineExecuted?.Invoke(e);
|
||||||
@@ -138,7 +143,7 @@ public class YesNtInterpreter
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeInfo.CurrentLine = runtimeInfo.Lines[runtimeInfo.LineNumber].Content.TrimEnd().Replace("\r", string.Empty);
|
runtimeInfo.CurrentLine = runtimeInfo.Lines[runtimeInfo.LineNumber].Content.Trim(' ').Replace("\r", string.Empty);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(runtimeInfo.CurrentLine) || runtimeInfo.CurrentLine.StartsWith('#'))
|
if (string.IsNullOrWhiteSpace(runtimeInfo.CurrentLine) || runtimeInfo.CurrentLine.StartsWith('#'))
|
||||||
{
|
{
|
||||||
@@ -187,7 +192,7 @@ public class YesNtInterpreter
|
|||||||
SpaceAround.StartEnd => $" {statementAttribute.Name.Trim()} ",
|
SpaceAround.StartEnd => $" {statementAttribute.Name.Trim()} ",
|
||||||
SpaceAround.Start => $" {statementAttribute.Name.Trim()}",
|
SpaceAround.Start => $" {statementAttribute.Name.Trim()}",
|
||||||
SpaceAround.End => $"{statementAttribute.Name.Trim()} ",
|
SpaceAround.End => $"{statementAttribute.Name.Trim()} ",
|
||||||
_ => statementAttribute.Name
|
_ => statementAttribute.Name.Trim()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (statementAttribute.Seperator is null || runtimeInfo.CurrentLine.Contains(statementAttribute.Seperator))
|
if (statementAttribute.Seperator is null || runtimeInfo.CurrentLine.Contains(statementAttribute.Seperator))
|
||||||
@@ -198,16 +203,11 @@ public class YesNtInterpreter
|
|||||||
statement.Value.Invoke(copyLine);
|
statement.Value.Invoke(copyLine);
|
||||||
statementFound = true;
|
statementFound = true;
|
||||||
}
|
}
|
||||||
else if (statementAttribute.SearchMode == SearchMode.Contains && $" {runtimeInfo.CurrentLine} ".Contains(name))
|
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);
|
string copyLine = statementAttribute.KeepStatementInArgs ? runtimeInfo.CurrentLine : runtimeInfo.CurrentLine.Replace(name, string.Empty);
|
||||||
statement.Value.Invoke(copyLine);
|
statement.Value.Invoke(copyLine);
|
||||||
statementFound = true;
|
statementFound = true;
|
||||||
|
|
||||||
runtimeInfo.CurrentLine = !leadingWhitespace ? runtimeInfo.CurrentLine.Trim() : runtimeInfo.CurrentLine.TrimEnd();
|
|
||||||
}
|
}
|
||||||
else if (statementAttribute.SearchMode == SearchMode.EndOfLine && runtimeInfo.CurrentLine.EndsWith(name))
|
else if (statementAttribute.SearchMode == SearchMode.EndOfLine && runtimeInfo.CurrentLine.EndsWith(name))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ internal class ConsoleStatements : StatementRuntimeInformation
|
|||||||
RuntimeInfo.Write(args);
|
RuntimeInfo.Write(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Statement("%crl", SearchMode.Contains, SpaceAround.End, ConsoleColor.DarkGreen, KeepStatementInArgs = true, Priority = Priority.Highest)]
|
[Statement("%crl", SearchMode.Contains, SpaceAround.None, ConsoleColor.DarkGreen, KeepStatementInArgs = true, Priority = Priority.Highest)]
|
||||||
public void ReadLine(string args)
|
public void ReadLine(string args)
|
||||||
{
|
{
|
||||||
args += " ";
|
args += " ";
|
||||||
while (args.Contains("%crl "))
|
while (args.Contains("%crl"))
|
||||||
{
|
{
|
||||||
string input = Console.ReadLine();
|
string input = Console.ReadLine();
|
||||||
if (input is null)
|
if (input is null)
|
||||||
@@ -45,11 +45,11 @@ internal class ConsoleStatements : StatementRuntimeInformation
|
|||||||
RuntimeInfo.CurrentLine = args.TrimEnd();
|
RuntimeInfo.CurrentLine = args.TrimEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Statement("%cr", SearchMode.Contains, SpaceAround.End, ConsoleColor.DarkGreen, KeepStatementInArgs = true, Priority = Priority.Highest)]
|
[Statement("%cr", SearchMode.Contains, SpaceAround.None, ConsoleColor.DarkGreen, KeepStatementInArgs = true, Priority = Priority.Highest)]
|
||||||
public void ReadKey(string args)
|
public void ReadKey(string args)
|
||||||
{
|
{
|
||||||
args += " ";
|
args += " ";
|
||||||
while (args.Contains("%cr "))
|
while (args.Contains("%cr"))
|
||||||
{
|
{
|
||||||
string input = ConsoleExtentions.ReadKey(RuntimeInfo).ToString();
|
string input = ConsoleExtentions.ReadKey(RuntimeInfo).ToString();
|
||||||
args = args.ReplaceFirstOccurrence("%cr ", input.ToSafeString() + " ");
|
args = args.ReplaceFirstOccurrence("%cr ", input.ToSafeString() + " ");
|
||||||
|
|||||||
@@ -81,6 +81,15 @@ internal partial class ProcessingStatements : StatementRuntimeInformation
|
|||||||
ConsoleExtentions.Sleep(millisecondsTimeout, RuntimeInfo);
|
ConsoleExtentions.Sleep(millisecondsTimeout, RuntimeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Statement("len", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Magenta)]
|
||||||
|
public void Length(string args)
|
||||||
|
{
|
||||||
|
RuntimeInfo.InParametersStack.Clear();
|
||||||
|
RuntimeInfo.OutParametersStack.Clear();
|
||||||
|
|
||||||
|
RuntimeInfo.OutParametersStack.Push(args.FromSafeString().Length.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
[Statement("imp", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Magenta)]
|
[Statement("imp", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Magenta)]
|
||||||
public void Import(string path)
|
public void Import(string path)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Text.RegularExpressions;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
using YesNt.Interpreter.Attributes;
|
using YesNt.Interpreter.Attributes;
|
||||||
using YesNt.Interpreter.Enums;
|
using YesNt.Interpreter.Enums;
|
||||||
@@ -90,27 +89,20 @@ internal partial class VariableStatements : StatementRuntimeInformation
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (KeyValuePair<string, string> variable in RuntimeInfo.Variables)
|
|
||||||
{
|
|
||||||
RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{variable.Key}", variable.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, string> variable in RuntimeInfo.GloablVariables)
|
|
||||||
{
|
|
||||||
RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{variable.Key}", variable.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RuntimeInfo.IsSearching)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MatchCollection matches = VariableStatementRegex().Matches(RuntimeInfo.CurrentLine);
|
MatchCollection matches = VariableStatementRegex().Matches(RuntimeInfo.CurrentLine);
|
||||||
|
|
||||||
for (int i = 0; i < matches.Count; i++)
|
for (int i = 0; i < matches.Count; i++)
|
||||||
{
|
{
|
||||||
string varName = matches[i].Value.Replace(">", string.Empty);
|
string varName = matches[i].Value.Replace(">", string.Empty);
|
||||||
if (!RuntimeInfo.Variables.ContainsKey(varName) && !RuntimeInfo.GloablVariables.ContainsKey(varName))
|
if (RuntimeInfo.Variables.TryGetValue(varName, out string value))
|
||||||
|
{
|
||||||
|
RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{varName}", value);
|
||||||
|
}
|
||||||
|
else if (RuntimeInfo.GloablVariables.TryGetValue(varName, out value))
|
||||||
|
{
|
||||||
|
RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{varName}", value);
|
||||||
|
}
|
||||||
|
else if (!RuntimeInfo.IsSearching)
|
||||||
{
|
{
|
||||||
RuntimeInfo.Exit($"Variable \"{varName}\" not found", true);
|
RuntimeInfo.Exit($"Variable \"{varName}\" not found", true);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -13,12 +13,16 @@ public static class StringExtentions
|
|||||||
{
|
{
|
||||||
_ = output.Append($"\v{c}\v");
|
_ = output.Append($"\v{c}\v");
|
||||||
}
|
}
|
||||||
return output.ToString();
|
return output
|
||||||
|
.ToString()
|
||||||
|
.Replace(' ', '~');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FromSafeString(this string input)
|
public static string FromSafeString(this string input)
|
||||||
{
|
{
|
||||||
return input.Replace("\v", "");
|
return input
|
||||||
|
.Replace("\v", "")
|
||||||
|
.Replace('~', ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ToStandardizedNumber(this string input, out double result)
|
public static bool ToStandardizedNumber(this string input, out double result)
|
||||||
|
|||||||
Reference in New Issue
Block a user