diff --git a/YesNt-Interpreter/Program.cs b/YesNt-Interpreter/Program.cs index 1923d00..29ec627 100644 --- a/YesNt-Interpreter/Program.cs +++ b/YesNt-Interpreter/Program.cs @@ -1,12 +1,21 @@ -namespace YesNt.Interpreter +using System; + +namespace YesNt.Interpreter { internal class Program { private static void Main(string[] args) { - YesNtInterpreter interpreter = new YesNtInterpreter(); - interpreter.Initialize(); - interpreter.Execute(args[0]); + if (args.Length == 1) + { + YesNtInterpreter interpreter = new YesNtInterpreter(); + interpreter.Initialize(); + interpreter.Execute(args[0]); + } + else + { + Console.WriteLine("No path specified!"); + } } } } \ No newline at end of file diff --git a/YesNt-Interpreter/Runtime/RuntimeInformation.cs b/YesNt-Interpreter/Runtime/RuntimeInformation.cs index f71c759..852efdf 100644 --- a/YesNt-Interpreter/Runtime/RuntimeInformation.cs +++ b/YesNt-Interpreter/Runtime/RuntimeInformation.cs @@ -1,12 +1,15 @@ using System; using System.Collections.Generic; +using YesNt.Interpreter.Runtime; using YesNt.Interpreter.Utilities; namespace YesNt.Interpreter { internal class RuntimeInformation { + private RuntimeInformation parentRuntimeInformation; + public Dictionary Variables { get; } = new(); public Dictionary Labels { get; } = new(); public List Lines { get; set; } = new(); @@ -15,15 +18,52 @@ namespace YesNt.Interpreter public string SearchLabel { get; set; } = string.Empty; public int LineNumber { get; set; } = 0; public bool Stop { get; private set; } = false; - public bool IsDebugMode { get; set; } + 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 RuntimeInformation ParentRuntimeInformation + { + get => parentRuntimeInformation; + set + { + parentRuntimeInformation = value; + if (parentRuntimeInformation is not null) + { + parentRuntimeInformation.OnExit += ParentRuntimeInformation_OnExit; + } + } + } + + private event Action OnExit; public event Action OnDebugOutput; + public event Action OnLineExecuted; + + private void ParentRuntimeInformation_OnExit(string exitMessage, bool stopChildTasks) + { + Exit($"Parent task was terminated!", stopChildTasks); + } + public void WriteLine(string output) { + if (Stop) + { + return; + } + if (IsDebugMode) { - OnDebugOutput?.Invoke(output.FromSaveString() + Environment.NewLine); + if (IsTask) + { + parentRuntimeInformation.WriteLine(output.FromSaveString() + Environment.NewLine); + } + else + { + OnDebugOutput?.Invoke(output.FromSaveString() + Environment.NewLine); + } } else { @@ -33,9 +73,21 @@ namespace YesNt.Interpreter public void Write(string output) { + if (Stop) + { + return; + } + if (IsDebugMode) { - OnDebugOutput?.Invoke(output.FromSaveString()); + if (IsTask) + { + parentRuntimeInformation.Write(output.FromSaveString()); + } + else + { + OnDebugOutput?.Invoke(output.FromSaveString()); + } } else { @@ -43,21 +95,45 @@ namespace YesNt.Interpreter } } - public void Exit(string message) + public void Exit(string message, bool stopAllTasks) { - WriteLine($"{Environment.NewLine}[The process was terminated at line {LineNumber + 1} with the message: {message}]"); - Stop = true; + if (!Stop) + { + WriteLine($"{Environment.NewLine}[{(IsTask ? "A child task" : "The process")} was terminated at line {LineNumber + 1} with the message: {message}]"); + Stop = true; + } + if (stopAllTasks == true && StopAllTasks == false) + { + 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() { - CurrentLine = string.Empty; Lines.Clear(); Variables.Clear(); Labels.Clear(); LabelStack.Clear(); + ParentRuntimeInformation = null; SearchLabel = string.Empty; + CurrentFilePath = string.Empty; + CurrentLine = string.Empty; Stop = false; + StopAllTasks = false; IsDebugMode = false; LineNumber = 0; } diff --git a/YesNt-Interpreter/Runtime/YesNtInterpreter.cs b/YesNt-Interpreter/Runtime/YesNtInterpreter.cs index c520cb3..346f799 100644 --- a/YesNt-Interpreter/Runtime/YesNtInterpreter.cs +++ b/YesNt-Interpreter/Runtime/YesNtInterpreter.cs @@ -40,6 +40,11 @@ namespace YesNt.Interpreter public event Action OnDebugOutput; + public void Stop() + { + runtimeInfo.Exit("Terminated by external process", true); + } + public void Initialize() { Assembly assembly = Assembly.GetExecutingAssembly(); @@ -80,6 +85,7 @@ namespace YesNt.Interpreter staticStatements = staticStatements.OrderBy(s => s.Key.Priority).ToList(); runtimeInfo.OnDebugOutput += (s) => OnDebugOutput?.Invoke(s); + runtimeInfo.OnLineExecuted += (DebugEventArgs e) => OnLineExecuted.Invoke(e); } public void Execute(string path, bool isDebugMode = false) @@ -87,8 +93,27 @@ namespace YesNt.Interpreter runtimeInfo.Reset(); runtimeInfo.IsDebugMode = isDebugMode; LoadFile(path); + Execute(); + } - for (runtimeInfo.LineNumber = 0; runtimeInfo.LineNumber < runtimeInfo.Lines.Count; runtimeInfo.LineNumber++) + internal void Execute(List lines, int startLine, RuntimeInformation parentRuntimeInformation) + { + runtimeInfo.Reset(); + runtimeInfo.IsDebugMode = parentRuntimeInformation.IsDebugMode; + runtimeInfo.Lines = lines; + runtimeInfo.LineNumber = startLine; + runtimeInfo.ParentRuntimeInformation = parentRuntimeInformation; + if (parentRuntimeInformation.StopAllTasks) + { + runtimeInfo.Exit($"Parent task was terminated!", parentRuntimeInformation.StopAllTasks); + return; + } + Execute(); + } + + private void Execute() + { + for (; runtimeInfo.LineNumber < runtimeInfo.Lines.Count; runtimeInfo.LineNumber++) { if (runtimeInfo.Stop) { @@ -173,18 +198,25 @@ namespace YesNt.Interpreter if (!statementFound) { - runtimeInfo.Exit("Invalid statement"); + runtimeInfo.Exit("Invalid statement", true); } - if (isDebugMode && searchingLabel) + if (runtimeInfo.IsDebugMode && searchingLabel) { debugEventArgs.CurrentLine = runtimeInfo.CurrentLine.FromSaveString(); - OnLineExecuted?.Invoke(debugEventArgs); + runtimeInfo.LineExecuted(debugEventArgs); } } if (runtimeInfo.Stop == false) { - runtimeInfo.Exit("End of file"); + if (string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel)) + { + runtimeInfo.Exit("End of file", false); + } + else + { + runtimeInfo.Exit($"Label \"{runtimeInfo.SearchLabel}\" not found", false); + } } } @@ -192,7 +224,7 @@ namespace YesNt.Interpreter { if (!File.Exists(path)) { - runtimeInfo.WriteLine($"File \"{path}\" not found!"); + runtimeInfo.Exit($"File \"{path}\" not found!", true); return; } diff --git a/YesNt-Interpreter/Statements.cs b/YesNt-Interpreter/Statements.cs deleted file mode 100644 index 1958c56..0000000 --- a/YesNt-Interpreter/Statements.cs +++ /dev/null @@ -1,199 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; - -using YesNt.Interpreter.Attributes; -using YesNt.Interpreter.Enums; -using YesNt.Interpreter.Utilities; - -namespace YesNt.Interpreter -{ - internal class Statements : StatementRuntimeInformation - { - [Statement("cwl", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)] - public void WriteLine(string args) - { - RuntimeInfo.WriteLine(args); - } - - [Statement("cw", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)] - public void Write(string args) - { - RuntimeInfo.Write(args); - } - - [Statement("%crl", SearchMode.Contains, SpaceAround.End, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void ReadLine(string args) - { - args += " "; - while (args.Contains("%crl ")) - { - args = args.ReplaceFirstOccurrence("%crl ", Console.ReadLine().ToSaveString() + " "); - } - RuntimeInfo.CurrentLine = args.TrimEnd(); - } - - [Statement("%cr", SearchMode.Contains, SpaceAround.End, KeepStatementInArgs = true, Priority = Priority.Highest)] - public void ReadKey(string args) - { - args += " "; - while (args.Contains("%cr ")) - { - args = args.ReplaceFirstOccurrence("%cr ", Console.ReadKey().KeyChar.ToString().ToSaveString() + " "); - } - RuntimeInfo.CurrentLine = args.TrimEnd(); - } - - [Statement("jmp", SearchMode.StartOfLine, SpaceAround.End)] - public void Jump(string args) - { - string key = args.Trim(); - 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)] - public void JumpIf(string args) - { - string[] parts = args.Split('|'); - if (parts.Length != 2) - { - RuntimeInfo.Exit("Invalid syntax"); - 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"); - } - return; - } - - 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, 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("ret", SearchMode.Exact, SpaceAround.None)] - public void Return(string _) - { - if (RuntimeInfo.LabelStack.Count > 0) - { - RuntimeInfo.LineNumber = RuntimeInfo.LabelStack.Pop(); - } - else - { - RuntimeInfo.Exit("No label in stack"); - } - } - - [Statement("end", SearchMode.Exact, SpaceAround.None)] - public void End(string _) - { - RuntimeInfo.Exit("Planned termination by code"); - } - - [Statement("!calc", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.High, ExecuteInSearchLabelMode = 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]+(\)?)+"); - - for (int i = 0; i < matches.Count; i++) - { - string res = Evaluator.Calculate(matches[i].Value); - if (res is null) - { - RuntimeInfo.Exit("Invalid operation"); - return; - } - args = args.Replace(matches[0].Value, res); - } - - RuntimeInfo.CurrentLine = args; - } - - [Statement("!eval", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.VeryHigh, ExecuteInSearchLabelMode = true)] - public void Evaluate(string args) - { - RuntimeInfo.CurrentLine = args.FromSaveString(); - } - - [Statement("<", SearchMode.StartOfLine, SpaceAround.None, Priority = Priority.VeryLow, IgnoreSyntaxHighlighting = true)] - public void DefineVariable(string args) - { - string[] parts = args.Split('='); - if (parts.Length == 2) - { - string key = parts[0].Replace("<", "").Trim(); - if (RuntimeInfo.Variables.ContainsKey(key)) - { - RuntimeInfo.Variables[key] = parts[1].Trim(); - } - else - { - RuntimeInfo.Variables.Add(key, parts[1].Trim()); - } - } - else - { - RuntimeInfo.Exit("Invalid syntax"); - return; - } - } - - [StaticStatement(ExecuteInSearchLabelMode = true)] - public void ReadVariable() - { - if (!RuntimeInfo.CurrentLine.Contains('>')) - { - return; - } - - foreach (KeyValuePair variable in RuntimeInfo.Variables) - { - RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{variable.Key}", variable.Value); - } - } - } -} \ No newline at end of file diff --git a/YesNt-Interpreter/Statements/CodeFlowStatements.cs b/YesNt-Interpreter/Statements/CodeFlowStatements.cs new file mode 100644 index 0000000..a661c4d --- /dev/null +++ b/YesNt-Interpreter/Statements/CodeFlowStatements.cs @@ -0,0 +1,112 @@ +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, 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, Priority = Priority.VeryLow)] + 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, 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("ret", SearchMode.Exact, SpaceAround.None)] + 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)] + public void End(string _) + { + RuntimeInfo.Exit("Planned termination by code", false); + } + + [Statement("trm", SearchMode.Exact, SpaceAround.None)] + public void Terminate(string _) + { + 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 new file mode 100644 index 0000000..ef9a9a7 --- /dev/null +++ b/YesNt-Interpreter/Statements/ConsoleStatements.cs @@ -0,0 +1,52 @@ +using System; + +using YesNt.Interpreter.Attributes; +using YesNt.Interpreter.Enums; +using YesNt.Interpreter.Utilities; + +namespace YesNt.Interpreter.Statements +{ + internal class ConsoleStatements : StatementRuntimeInformation + { + [Statement("cwl", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)] + public void WriteLine(string args) + { + RuntimeInfo.WriteLine(args); + } + + [Statement("cw", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)] + public void Write(string args) + { + RuntimeInfo.Write(args); + } + + [Statement("%crl", SearchMode.Contains, SpaceAround.End, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void ReadLine(string args) + { + args += " "; + while (args.Contains("%crl ")) + { + string input = Console.ReadLine(); + if (input is null) + { + RuntimeInfo.Exit("Terminated by external process", true); + return; + } + args = args.ReplaceFirstOccurrence("%crl ", input.ToSaveString() + " "); + } + RuntimeInfo.CurrentLine = args.TrimEnd(); + } + + [Statement("%cr", SearchMode.Contains, SpaceAround.End, KeepStatementInArgs = true, Priority = Priority.Highest)] + public void ReadKey(string args) + { + args += " "; + while (args.Contains("%cr ")) + { + string input = ConsoleExtentions.ReadKey(RuntimeInfo).ToString(); + args = args.ReplaceFirstOccurrence("%cr ", input.ToSaveString() + " "); + } + RuntimeInfo.CurrentLine = args.TrimEnd(); + } + } +} \ No newline at end of file diff --git a/YesNt-Interpreter/Statements/ProcessingStatements.cs b/YesNt-Interpreter/Statements/ProcessingStatements.cs new file mode 100644 index 0000000..9360727 --- /dev/null +++ b/YesNt-Interpreter/Statements/ProcessingStatements.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +using YesNt.Interpreter.Attributes; +using YesNt.Interpreter.Enums; +using YesNt.Interpreter.Utilities; + +namespace YesNt.Interpreter.Statements +{ + internal class ProcessingStatements : StatementRuntimeInformation + { + [Statement("!calc", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.High, ExecuteInSearchLabelMode = 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]+(\)?)+"); + + for (int i = 0; i < matches.Count; i++) + { + string res = Evaluator.Calculate(matches[i].Value); + if (res is null) + { + RuntimeInfo.Exit("Invalid operation", true); + return; + } + args = args.Replace(matches[0].Value, res); + } + + RuntimeInfo.CurrentLine = args; + } + + [Statement("!eval", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.VeryHigh)] + public void Evaluate(string args) + { + RuntimeInfo.CurrentLine = args.FromSaveString(); + } + + [Statement("!task", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.VeryHigh)] + public void RunTask(string line) + { + int lineNumer = RuntimeInfo.LineNumber; + List lines = RuntimeInfo.Lines.GetRange(0, RuntimeInfo.Lines.Count); + lines[lineNumer] = line; + _ = Task.Run(() => + { + YesNtInterpreter interpreter = new YesNtInterpreter(); + interpreter.Initialize(); + interpreter.Execute(lines, lineNumer, RuntimeInfo); + }); + + RuntimeInfo.CurrentLine = string.Empty; + } + + [Statement("slp", SearchMode.StartOfLine, SpaceAround.End)] + public void Sleep(string args) + { + _ = int.TryParse(args, out int millisecondsTimeout); + ConsoleExtentions.Sleep(millisecondsTimeout, RuntimeInfo); + } + + [Statement("imp", SearchMode.StartOfLine, SpaceAround.End)] + public void Import(string path) + { + if (string.IsNullOrEmpty(Path.GetExtension(path))) + { + path = Path.ChangeExtension(path, "ynt"); + } + + if (File.Exists(path)) + { + try + { + RuntimeInfo.Lines.RemoveAt(0); + RuntimeInfo.Lines.InsertRange(RuntimeInfo.LineNumber, File.ReadAllLines(path)); + RuntimeInfo.LineNumber--; + } + catch + { + RuntimeInfo.Exit($"Could not load file {path}", true); + } + } + else + { + RuntimeInfo.Exit($"Could not find file {path}", true); + } + } + } +} \ No newline at end of file diff --git a/YesNt-Interpreter/Statements/VariableStatements.cs b/YesNt-Interpreter/Statements/VariableStatements.cs new file mode 100644 index 0000000..f7716f0 --- /dev/null +++ b/YesNt-Interpreter/Statements/VariableStatements.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; + +using YesNt.Interpreter.Attributes; +using YesNt.Interpreter.Enums; + +namespace YesNt.Interpreter.Statements +{ + internal class VariableStatements : StatementRuntimeInformation + { + [Statement("<", SearchMode.StartOfLine, SpaceAround.None, Priority = Priority.VeryLow, IgnoreSyntaxHighlighting = true)] + public void DefineVariable(string args) + { + string[] parts = args.Split('='); + if (parts.Length == 2) + { + string key = parts[0].Replace("<", "").Trim(); + if (key.Contains(' ')) + { + RuntimeInfo.Exit("Invalid Syntax", true); + } + + if (RuntimeInfo.Variables.ContainsKey(key)) + { + RuntimeInfo.Variables[key] = parts[1].Trim(); + } + else + { + RuntimeInfo.Variables.Add(key, parts[1].Trim()); + } + } + else + { + RuntimeInfo.Exit("Invalid syntax", true); + return; + } + } + + [StaticStatement(ExecuteInSearchLabelMode = true)] + public void ReadVariable() + { + if (!RuntimeInfo.CurrentLine.Contains('>')) + { + return; + } + + foreach (KeyValuePair variable in RuntimeInfo.Variables) + { + RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{variable.Key}", variable.Value); + } + } + } +} \ No newline at end of file diff --git a/YesNt-Interpreter/Utilities/ConsoleExtentions.cs b/YesNt-Interpreter/Utilities/ConsoleExtentions.cs new file mode 100644 index 0000000..efb0ead --- /dev/null +++ b/YesNt-Interpreter/Utilities/ConsoleExtentions.cs @@ -0,0 +1,36 @@ +using System; +using System.Diagnostics; +using System.Threading; + +namespace YesNt.Interpreter.Utilities +{ + internal static class ConsoleExtentions + { + public static char ReadKey(RuntimeInformation runtimeInformation) + { + while (!runtimeInformation.Stop) + { + if (Console.KeyAvailable) + { + return Console.ReadKey().KeyChar; + } + Thread.Sleep(10); + } + return ' '; + } + + public static void Sleep(int millisecondsTimeout, RuntimeInformation runtimeInformation) + { + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + while (!runtimeInformation.Stop) + { + if (stopwatch.ElapsedMilliseconds > millisecondsTimeout) + { + return; + } + Thread.Sleep(10); + } + } + } +} \ No newline at end of file diff --git a/YesNt-Interpreter/Utilities/Evaluator.cs b/YesNt-Interpreter/Utilities/Evaluator.cs index 581fb71..83fdb12 100644 --- a/YesNt-Interpreter/Utilities/Evaluator.cs +++ b/YesNt-Interpreter/Utilities/Evaluator.cs @@ -77,10 +77,6 @@ namespace YesNt.Interpreter.Utilities return null; } - /* - ((\)?)+(\(?)+[0-9]+(((\s?)+(\)?)(\s?)+\+(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\-(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\*(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\/(\s?)+(\(?)+(\s?)+)|[,.])(?=[0-9])+)+[0-9]+(\)?)+ - */ - public static string Calculate(string input, char op = '+') { if (input is null) diff --git a/YesNt.CodeEditor/Editor.cs b/YesNt.CodeEditor/Editor.cs index f5755cc..22ace4c 100644 --- a/YesNt.CodeEditor/Editor.cs +++ b/YesNt.CodeEditor/Editor.cs @@ -32,6 +32,7 @@ namespace YesNt.CodeEditor yesNtInterpreter.OnDebugOutput += YesNtInterpreter_OnDebugOutput; yesNtInterpreter.OnLineExecuted += YesNtInterpreter_OnLineExecuted; syntaxHighlighter = new(yesNtInterpreter.StatementInformation); + Console.CancelKeyPress += Console_CancelKeyPress; } public void Run() @@ -230,19 +231,32 @@ namespace YesNt.CodeEditor case "run": if (Save(input, true)) { + mode = Mode.Debug; Console.Clear(); yesNtInterpreter.Execute(currentPath); + while (Console.KeyAvailable) + { + Console.ReadKey(true); + } Console.ReadKey(); + WriteStatus(string.Empty); + mode = Mode.Command; } break; case "debug": if (Save(input, true)) { + mode = Mode.Debug; Console.Clear(); yesNtInterpreter.Execute(currentPath, true); + while (Console.KeyAvailable) + { + Console.ReadKey(true); + } Console.ReadKey(); WriteStatus(string.Empty); + mode = Mode.Command; } break; @@ -257,12 +271,6 @@ namespace YesNt.CodeEditor break; } - if (!File.Exists(path)) - { - WriteStatus("File does not exist!"); - break; - } - try { Load(path); @@ -277,15 +285,13 @@ namespace YesNt.CodeEditor break; case "new": - if (Save(input, false)) - { - lineOffset = 0; - cursorPosition.X = 0; - cursorPosition.Y = 0; - currentPath = string.Empty; - lines.Clear(); - WriteStatus(string.Empty); - } + + lineOffset = 0; + cursorPosition.X = 0; + cursorPosition.Y = 0; + currentPath = string.Empty; + lines.Clear(); + WriteStatus(string.Empty); break; case "exit": @@ -302,6 +308,11 @@ namespace YesNt.CodeEditor private bool Load(string path) { + if (string.IsNullOrEmpty(Path.GetExtension(path))) + { + path = Path.ChangeExtension(path, "ynt"); + } + if (!File.Exists(path)) { WriteStatus("File does not exist!"); @@ -321,7 +332,6 @@ namespace YesNt.CodeEditor private bool Save(string input, bool loadIfExists) { string text = ""; - string path = ""; foreach (string line in lines) { @@ -329,6 +339,7 @@ namespace YesNt.CodeEditor } text = text.TrimEnd('\n'); + string path; if (input.Split(' ').Length == 2) { path = input.Split(' ')[1]; @@ -361,6 +372,11 @@ namespace YesNt.CodeEditor return false; } + if (string.IsNullOrEmpty(Path.GetExtension(path))) + { + path = Path.ChangeExtension(path, "ynt"); + } + try { File.WriteAllText(path, text); @@ -404,6 +420,16 @@ namespace YesNt.CodeEditor } debugOutput.Clear(); } + + private void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) + { + e.Cancel = true; + if (mode == Mode.Debug) + { + yesNtInterpreter.Stop(); + mode = Mode.Command; + } + } } internal class Point @@ -421,6 +447,7 @@ namespace YesNt.CodeEditor internal enum Mode { Edit, - Command + Command, + Debug } } \ No newline at end of file diff --git a/YesNt.CodeEditor/Program.cs b/YesNt.CodeEditor/Program.cs index 01f8547..a631dbe 100644 --- a/YesNt.CodeEditor/Program.cs +++ b/YesNt.CodeEditor/Program.cs @@ -1,6 +1,4 @@ -using System; - -namespace YesNt.CodeEditor +namespace YesNt.CodeEditor { internal class Program { @@ -8,7 +6,6 @@ namespace YesNt.CodeEditor { TextEditor textEditor; - Console.CancelKeyPress += Console_CancelKeyPress; if (args.Length > 0) { textEditor = new TextEditor(args[0]); @@ -20,10 +17,5 @@ namespace YesNt.CodeEditor textEditor.Run(); } - - private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) - { - e.Cancel = true; - } } } \ No newline at end of file