- Add functions

- Code improvements
This commit is contained in:
Stone-Red-Code
2021-11-19 20:49:55 +01:00
parent 812b780942
commit 2a7e8074ba
27 changed files with 356 additions and 156 deletions
+8 -8
View File
@@ -1,11 +1,11 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 17
VisualStudioVersion = 16.0.31410.357 VisualStudioVersion = 17.0.31912.275
MinimumVisualStudioVersion = 10.0.40219.1 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 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -13,14 +13,14 @@ Global
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution 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.ActiveCfg = Debug|Any CPU
{33BDA036-A37E-475E-AACF-8ED96E31BA1A}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{33BDA036-A37E-475E-AACF-8ED96E31BA1A}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -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);
}
}
}
+7 -7
View File
@@ -12,7 +12,7 @@ namespace YesNt.CodeEditor
private readonly SyntaxHighlighter syntaxHighlighter; private readonly SyntaxHighlighter syntaxHighlighter;
private readonly List<string> debugOutput = new(); private readonly List<string> debugOutput = new();
public YesNtInterpreter yesNtInterpreter { get; } = new(); public YesNtInterpreter YesNtInterpreter { get; } = new();
public int LineOffset { get; set; } = 0; public int LineOffset { get; set; } = 0;
public List<string> Lines { get; } = new(); public List<string> Lines { get; } = new();
public Point CursorPosition { get; } = new(0, 0); public Point CursorPosition { get; } = new(0, 0);
@@ -29,10 +29,10 @@ namespace YesNt.CodeEditor
public TextEditor() public TextEditor()
{ {
yesNtInterpreter.Initialize(); YesNtInterpreter.Initialize();
yesNtInterpreter.OnDebugOutput += YesNtInterpreter_OnDebugOutput; YesNtInterpreter.OnDebugOutput += YesNtInterpreter_OnDebugOutput;
yesNtInterpreter.OnLineExecuted += YesNtInterpreter_OnLineExecuted; YesNtInterpreter.OnLineExecuted += YesNtInterpreter_OnLineExecuted;
syntaxHighlighter = new(yesNtInterpreter.StatementInformation); syntaxHighlighter = new(YesNtInterpreter.StatementInformation);
inputHandler = new InputHandler(this); inputHandler = new InputHandler(this);
Console.CancelKeyPress += Console_CancelKeyPress; Console.CancelKeyPress += Console_CancelKeyPress;
} }
@@ -198,7 +198,7 @@ namespace YesNt.CodeEditor
Console.ForegroundColor = ConsoleColor.Magenta; Console.ForegroundColor = ConsoleColor.Magenta;
string sharedString = (Console.CursorLeft != 0) ? Environment.NewLine : string.Empty; 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) if (e.OriginalLine == e.CurrentLine)
{ {
@@ -226,7 +226,7 @@ namespace YesNt.CodeEditor
switch (EditMode) switch (EditMode)
{ {
case Mode.Debug: case Mode.Debug:
yesNtInterpreter.Stop(); YesNtInterpreter.Stop();
EditMode = Mode.Command; EditMode = Mode.Command;
break; break;
} }
+2 -2
View File
@@ -233,7 +233,7 @@ namespace YesNt.CodeEditor
textEditor.EditMode = Mode.Debug; textEditor.EditMode = Mode.Debug;
Console.Clear(); Console.Clear();
Console.CursorVisible = true; Console.CursorVisible = true;
textEditor.yesNtInterpreter.Execute(textEditor.CurrentPath); textEditor.YesNtInterpreter.Execute(textEditor.CurrentPath);
while (Console.KeyAvailable) while (Console.KeyAvailable)
{ {
Console.ReadKey(true); Console.ReadKey(true);
@@ -250,7 +250,7 @@ namespace YesNt.CodeEditor
textEditor.EditMode = Mode.Debug; textEditor.EditMode = Mode.Debug;
Console.Clear(); Console.Clear();
Console.CursorVisible = true; Console.CursorVisible = true;
textEditor.yesNtInterpreter.Execute(textEditor.CurrentPath, true); textEditor.YesNtInterpreter.Execute(textEditor.CurrentPath, true);
while (Console.KeyAvailable) while (Console.KeyAvailable)
{ {
Console.ReadKey(true); Console.ReadKey(true);
+1 -1
View File
@@ -6,7 +6,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\YesNt-Interpreter\YesNt.Interpreter.csproj" /> <ProjectReference Include="..\YesNt.Interpreter\YesNt.Interpreter.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -12,7 +12,7 @@ namespace YesNt.Interpreter.Attributes
public SpaceAround SpaceAround { get; } public SpaceAround SpaceAround { get; }
public ConsoleColor Color { get; set; } public ConsoleColor Color { get; set; }
public Priority Priority { get; set; } = Priority.Normal; public Priority Priority { get; set; } = Priority.Normal;
public bool ExecuteInSearchLabelMode { get; set; } public bool ExecuteInSearchMode { get; set; }
public bool KeepStatementInArgs { get; set; } public bool KeepStatementInArgs { get; set; }
public bool IgnoreSyntaxHighlighting { get; } public bool IgnoreSyntaxHighlighting { get; }
public string Seperator { get; set; } public string Seperator { get; set; }
@@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace YesNt.Interpreter.Runtime
{
internal class FunctionScope
{
public int CallerLine { get; }
public Dictionary<string, string> Variables { get; } = new();
public FunctionScope(int callerLine)
{
CallerLine = callerLine;
}
}
}
@@ -11,23 +11,47 @@ namespace YesNt.Interpreter
private RuntimeInformation parentRuntimeInformation; private RuntimeInformation parentRuntimeInformation;
private static int internalTaskId = 0; private static int internalTaskId = 0;
private int taskId = 0; private int taskId = 0;
private readonly Dictionary<string, string> topVariables = new();
public Dictionary<string, string> Variables { get; } = new();
public Dictionary<string, string> GloablVariables { get; set; } = new(); public Dictionary<string, string> GloablVariables { get; set; } = new();
public Dictionary<string, int> Labels { get; } = new(); public Dictionary<string, int> Labels { get; } = new();
public Dictionary<string, int> Functions { get; } = new();
public Stack<FunctionScope> FunctionCallStack { get; } = new();
public List<string> Lines { get; set; } = new(); public List<string> Lines { get; set; } = new();
public string CurrentLine { get; set; } = string.Empty; public string CurrentLine { get; set; } = string.Empty;
public Stack<int> LabelStack { get; set; } = new();
public string SearchLabel { 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 int LineNumber { get; set; } = 0;
public bool Stop { get; private set; } = false; public bool Stop { get; private set; } = false;
public bool StopAllTasks { get; private set; } = false; public bool StopAllTasks { get; private set; } = false;
public bool IsDebugMode { get; set; } = false; public bool IsDebugMode { get; set; } = false;
public string CurrentFilePath { get; set; } = string.Empty; public string CurrentFilePath { get; set; } = string.Empty;
public bool IsTask => ParentRuntimeInformation is not null; public bool IsTask => ParentRuntimeInformation is not null;
public int TaskId => IsTask ? taskId : 0; 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<string, string> Variables
{
get
{
if (FunctionCallStack.Count == 0)
{
return topVariables;
}
else
{
return FunctionCallStack.Peek().Variables;
}
}
}
public RuntimeInformation ParentRuntimeInformation public RuntimeInformation ParentRuntimeInformation
{ {
get => parentRuntimeInformation; get => parentRuntimeInformation;
@@ -41,6 +65,8 @@ namespace YesNt.Interpreter
} }
} }
public bool IsSearching => !string.IsNullOrWhiteSpace(SearchLabel + SearchFunction) || IsInFunction && FunctionCallStack.Count == 0;
private event Action<string, bool> OnExit; private event Action<string, bool> OnExit;
public event Action<string> OnDebugOutput; public event Action<string> OnDebugOutput;
@@ -104,7 +130,7 @@ namespace YesNt.Interpreter
{ {
if (!Stop) 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; Stop = true;
} }
if (stopAllTasks == true && StopAllTasks == false) if (stopAllTasks == true && StopAllTasks == false)
@@ -129,18 +155,22 @@ namespace YesNt.Interpreter
public void Reset() public void Reset()
{ {
topVariables.Clear();
Lines.Clear(); Lines.Clear();
Variables.Clear();
GloablVariables.Clear(); GloablVariables.Clear();
Labels.Clear(); Labels.Clear();
LabelStack.Clear(); Functions.Clear();
FunctionCallStack.Clear();
ParentRuntimeInformation = null; ParentRuntimeInformation = null;
SearchLabel = string.Empty; SearchLabel = string.Empty;
SearchFunction = string.Empty;
CurrentFilePath = string.Empty; CurrentFilePath = string.Empty;
CurrentLine = string.Empty; CurrentLine = string.Empty;
Stop = false; Stop = false;
StopAllTasks = false; StopAllTasks = false;
IsDebugMode = false; IsDebugMode = false;
IsInFunction = false;
InternalIsInFunction = false;
LineNumber = 0; LineNumber = 0;
taskId = internalTaskId + 1; taskId = internalTaskId + 1;
internalTaskId++; internalTaskId++;
@@ -142,7 +142,7 @@ namespace YesNt.Interpreter
foreach (KeyValuePair<StaticStatementAttribute, Action> staticStatement in staticStatements) foreach (KeyValuePair<StaticStatementAttribute, Action> staticStatement in staticStatements)
{ {
StaticStatementAttribute staticStatementAttribute = staticStatement.Key; StaticStatementAttribute staticStatementAttribute = staticStatement.Key;
if (staticStatementAttribute.ExecuteInSearchLabelMode == false && !string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel)) if (staticStatementAttribute.ExecuteInSearchLabelMode == false && runtimeInfo.IsSearching)
{ {
continue; continue;
} }
@@ -151,13 +151,13 @@ namespace YesNt.Interpreter
} }
bool statementFound = false; bool statementFound = false;
bool searchingLabel = string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel); bool notSearchingLabel = !runtimeInfo.IsSearching;
foreach (KeyValuePair<StatementAttribute, Action<string>> statement in statements) foreach (KeyValuePair<StatementAttribute, Action<string>> statement in statements)
{ {
StatementAttribute statementAttribute = statement.Key; StatementAttribute statementAttribute = statement.Key;
if (statementAttribute.ExecuteInSearchLabelMode == false && !string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel)) if (statementAttribute.ExecuteInSearchMode == false && runtimeInfo.IsSearching)
{ {
statementFound = true; statementFound = true;
continue; continue;
@@ -184,10 +184,21 @@ namespace YesNt.Interpreter
} }
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} "; 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;
if (!leadingWhitespace)
{
runtimeInfo.CurrentLine = runtimeInfo.CurrentLine.Trim();
}
else
{
runtimeInfo.CurrentLine = runtimeInfo.CurrentLine.TrimEnd();
}
} }
else if (statementAttribute.SearchMode == SearchMode.EndOfLine && runtimeInfo.CurrentLine.EndsWith(name)) else if (statementAttribute.SearchMode == SearchMode.EndOfLine && runtimeInfo.CurrentLine.EndsWith(name))
{ {
@@ -206,7 +217,7 @@ namespace YesNt.Interpreter
{ {
runtimeInfo.Exit("Invalid statement", true); runtimeInfo.Exit("Invalid statement", true);
} }
if (runtimeInfo.IsDebugMode && searchingLabel) if (runtimeInfo.IsDebugMode && notSearchingLabel)
{ {
debugEventArgs.CurrentLine = runtimeInfo.CurrentLine.FromSaveString(); debugEventArgs.CurrentLine = runtimeInfo.CurrentLine.FromSaveString();
runtimeInfo.LineExecuted(debugEventArgs); runtimeInfo.LineExecuted(debugEventArgs);
@@ -215,14 +226,19 @@ namespace YesNt.Interpreter
if (runtimeInfo.Stop == false) if (runtimeInfo.Stop == false)
{ {
if (string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel)) if (!string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel))
{
runtimeInfo.Exit("End of file", false);
}
else
{ {
runtimeInfo.Exit($"Label \"{runtimeInfo.SearchLabel}\" not found", true); 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) if (runtimeInfo.IsDebugMode)
{ {
runtimeInfo.LineExecuted(null); runtimeInfo.LineExecuted(null);
@@ -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);
}
}
}
@@ -12,7 +12,7 @@ namespace YesNt.Interpreter.Statements
{ {
internal class ProcessingStatements : StatementRuntimeInformation 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) 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]+(\)?)+"); 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]+(\)?)+");
@@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions;
using YesNt.Interpreter.Attributes; using YesNt.Interpreter.Attributes;
using YesNt.Interpreter.Enums; using YesNt.Interpreter.Enums;
@@ -13,7 +14,7 @@ namespace YesNt.Interpreter.Statements
string[] parts = args.Split('='); string[] parts = args.Split('=');
if (parts.Length == 2) if (parts.Length == 2)
{ {
string key = parts[0].Replace("<", string.Empty).Trim(); string key = parts[0].Trim();
if (key.Contains(' ')) if (key.Contains(' '))
{ {
RuntimeInfo.Exit("Invalid Syntax", true); RuntimeInfo.Exit("Invalid Syntax", true);
@@ -41,7 +42,7 @@ namespace YesNt.Interpreter.Statements
string[] parts = args.Split('='); string[] parts = args.Split('=');
if (parts.Length == 2) if (parts.Length == 2)
{ {
string key = parts[0].Replace("!<", string.Empty).Trim(); string key = parts[0].Trim();
if (key.Contains(' ')) if (key.Contains(' '))
{ {
RuntimeInfo.Exit("Invalid Syntax", true); 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)] [StaticStatement(ExecuteInSearchLabelMode = true)]
public void ReadVariable() public void ReadVariable()
{ {
@@ -80,6 +100,23 @@ namespace YesNt.Interpreter.Statements
{ {
RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{variable.Key}", variable.Value); 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;
}
}
} }
} }
} }