mirror of
https://github.com/Stone-Red-Code/YesNt-Interpreter.git
synced 2026-09-04 00:56:31 +02:00
Add system statements ('exc')
This commit is contained in:
@@ -64,6 +64,9 @@ dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
|
||||
# S1172: Unused method parameters should be removed
|
||||
dotnet_diagnostic.S1172.severity = none
|
||||
|
||||
[*.{cs,vb}]
|
||||
#### Naming styles ####
|
||||
|
||||
|
||||
+15
-1
@@ -12,26 +12,40 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YesNt.Interpreter.Tests", "YesNt.Interpreter.Tests\YesNt.Interpreter.Tests.csproj", "{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YesNt.Interpreter.Tests", "YesNt.Interpreter.Tests\YesNt.Interpreter.Tests.csproj", "{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{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|x64.ActiveCfg = Debug|x64
|
||||
{33BDA036-A37E-475E-AACF-8ED96E31BA1A}.Debug|x64.Build.0 = Debug|x64
|
||||
{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|x64.ActiveCfg = Release|x64
|
||||
{33BDA036-A37E-475E-AACF-8ED96E31BA1A}.Release|x64.Build.0 = Release|x64
|
||||
{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}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E40573DB-912A-4871-BB65-3EE6E7D72E79}.Debug|x64.Build.0 = Debug|x64
|
||||
{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
|
||||
{E40573DB-912A-4871-BB65-3EE6E7D72E79}.Release|x64.ActiveCfg = Release|x64
|
||||
{E40573DB-912A-4871-BB65-3EE6E7D72E79}.Release|x64.Build.0 = Release|x64
|
||||
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Debug|x64.Build.0 = Debug|x64
|
||||
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Release|x64.ActiveCfg = Release|x64
|
||||
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"profiles": {
|
||||
"YesNt.CodeEditor": {
|
||||
"commandName": "Project"
|
||||
},
|
||||
"WSL": {
|
||||
"commandName": "WSL2",
|
||||
"environmentVariables": {},
|
||||
"distributionName": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using YesNt.Interpreter.Attributes;
|
||||
using YesNt.Interpreter.Enums;
|
||||
using YesNt.Interpreter.Runtime;
|
||||
using YesNt.Interpreter.Utilities;
|
||||
|
||||
namespace YesNt.Interpreter.Statements
|
||||
{
|
||||
internal class SystemStatements : StatementRuntimeInformation
|
||||
{
|
||||
[Statement("exc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Magenta, Priority = Priority.Low, Seperator = "|")]
|
||||
public void ExecuteProgramWithArgs(string input)
|
||||
{
|
||||
string[] parts = input.FromSaveString().Split('|');
|
||||
parts[0] = parts[0].Trim();
|
||||
|
||||
string[] functionArgumets = parts[1].Split(',');
|
||||
|
||||
foreach (string argumanet in functionArgumets)
|
||||
{
|
||||
RuntimeInfo.InParametersStack.Push(argumanet.Trim());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
StartProcess(parts[0], string.Join(string.Empty, RuntimeInfo.InParametersStack.Reverse()));
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
RuntimeInfo.Exit($"Cannot find file \"{parts[0]}\".", false);
|
||||
}
|
||||
catch (Win32Exception ex)
|
||||
{
|
||||
RuntimeInfo.Exit($"Failed to start \"{parts[0]}\". {ex.Message}", false);
|
||||
}
|
||||
|
||||
//HACK: Clear line to avoid execution from other "exc" statement
|
||||
RuntimeInfo.CurrentLine = string.Empty;
|
||||
}
|
||||
|
||||
[Statement("exc", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Magenta, Priority = Priority.VeryLow)]
|
||||
public void ExecuteProgram(string input)
|
||||
{
|
||||
try
|
||||
{
|
||||
StartProcess(input, string.Join(string.Empty, RuntimeInfo.InParametersStack.Reverse()));
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
RuntimeInfo.Exit($"Cannot find file \"{input}\".", false);
|
||||
}
|
||||
catch (Win32Exception ex)
|
||||
{
|
||||
RuntimeInfo.Exit($"Failed to start \"{input}\". {ex.Message}", false);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartProcess(string name, string args)
|
||||
{
|
||||
FixedProcess process = new FixedProcess
|
||||
{
|
||||
StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = name,
|
||||
Arguments = args,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
}
|
||||
};
|
||||
|
||||
process.OutputDataReceived += Process_OutputDataReceived;
|
||||
process.ErrorDataReceived += Process_ErrorDataReceived;
|
||||
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
process.WaitForExit();
|
||||
|
||||
RuntimeInfo.InParametersStack.Clear();
|
||||
RuntimeInfo.OutParametersStack.Clear();
|
||||
RuntimeInfo.OutParametersStack.Push(process.ExitCode.ToString());
|
||||
}
|
||||
|
||||
private void Process_ErrorDataReceived(object sender, Utilities.DataReceivedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RuntimeInfo.OutParametersStack.Push(e.Data);
|
||||
Console.Write("Error: " + e.Data);
|
||||
}
|
||||
|
||||
private void Process_OutputDataReceived(object sender, Utilities.DataReceivedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RuntimeInfo.OutParametersStack.Push(e.Data);
|
||||
Console.Write(e.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace YesNt.Interpreter.Utilities
|
||||
{
|
||||
internal delegate void UserCallBack(string data);
|
||||
|
||||
public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e);
|
||||
|
||||
public class FixedProcess : Process
|
||||
{
|
||||
internal AsyncStreamReader output;
|
||||
internal AsyncStreamReader error;
|
||||
|
||||
public new event DataReceivedEventHandler OutputDataReceived;
|
||||
|
||||
public new event DataReceivedEventHandler ErrorDataReceived;
|
||||
|
||||
public new void BeginOutputReadLine()
|
||||
{
|
||||
Stream baseStream = StandardOutput.BaseStream;
|
||||
output = new AsyncStreamReader(this, baseStream, new UserCallBack(FixedOutputReadNotifyUser), StandardOutput.CurrentEncoding);
|
||||
output.BeginReadLine();
|
||||
}
|
||||
|
||||
public new void BeginErrorReadLine()
|
||||
{
|
||||
Stream baseStream = StandardError.BaseStream;
|
||||
error = new AsyncStreamReader(this, baseStream, new UserCallBack(FixedErrorReadNotifyUser), StandardError.CurrentEncoding);
|
||||
error.BeginReadLine();
|
||||
}
|
||||
|
||||
internal void FixedOutputReadNotifyUser(string data)
|
||||
{
|
||||
DataReceivedEventHandler outputDataReceived = OutputDataReceived;
|
||||
if (outputDataReceived != null)
|
||||
{
|
||||
DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data);
|
||||
if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
|
||||
{
|
||||
SynchronizingObject.Invoke(outputDataReceived, new object[]
|
||||
{
|
||||
this,
|
||||
dataReceivedEventArgs
|
||||
});
|
||||
return;
|
||||
}
|
||||
outputDataReceived(this, dataReceivedEventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
internal void FixedErrorReadNotifyUser(string data)
|
||||
{
|
||||
DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
|
||||
if (errorDataReceived != null)
|
||||
{
|
||||
DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data);
|
||||
if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
|
||||
{
|
||||
SynchronizingObject.Invoke(errorDataReceived, new object[]
|
||||
{
|
||||
this,
|
||||
dataReceivedEventArgs
|
||||
});
|
||||
return;
|
||||
}
|
||||
errorDataReceived(this, dataReceivedEventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class AsyncStreamReader : IDisposable
|
||||
{
|
||||
internal const int DefaultBufferSize = 1024;
|
||||
private Stream stream;
|
||||
private Encoding encoding;
|
||||
private Decoder decoder;
|
||||
private byte[] byteBuffer;
|
||||
private char[] charBuffer;
|
||||
private UserCallBack userCallBack;
|
||||
private bool cancelOperation;
|
||||
private ManualResetEvent eofEvent;
|
||||
private readonly Queue messageQueue;
|
||||
private StringBuilder sb;
|
||||
private bool bLastCarriageReturn;
|
||||
public virtual Encoding CurrentEncoding => encoding;
|
||||
public virtual Stream BaseStream => stream;
|
||||
|
||||
internal AsyncStreamReader(Process process, Stream stream, UserCallBack callback, Encoding encoding) : this(process, stream, callback, encoding, 1024)
|
||||
{
|
||||
}
|
||||
|
||||
internal AsyncStreamReader(Process process, Stream stream, UserCallBack callback, Encoding encoding, int bufferSize)
|
||||
{
|
||||
Init(process, stream, callback, encoding, bufferSize);
|
||||
messageQueue = new Queue();
|
||||
}
|
||||
|
||||
private void Init(Process process, Stream stream, UserCallBack callback, Encoding encoding, int bufferSize)
|
||||
{
|
||||
this.stream = stream;
|
||||
this.encoding = encoding;
|
||||
userCallBack = callback;
|
||||
decoder = encoding.GetDecoder();
|
||||
if (bufferSize < 128)
|
||||
{
|
||||
bufferSize = 128;
|
||||
}
|
||||
byteBuffer = new byte[bufferSize];
|
||||
int _maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize);
|
||||
charBuffer = new char[_maxCharsPerBuffer];
|
||||
cancelOperation = false;
|
||||
eofEvent = new ManualResetEvent(false);
|
||||
sb = null;
|
||||
bLastCarriageReturn = false;
|
||||
}
|
||||
|
||||
public virtual void Close()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && stream != null)
|
||||
{
|
||||
stream.Close();
|
||||
}
|
||||
if (stream != null)
|
||||
{
|
||||
stream = null;
|
||||
encoding = null;
|
||||
decoder = null;
|
||||
byteBuffer = null;
|
||||
charBuffer = null;
|
||||
}
|
||||
if (eofEvent != null)
|
||||
{
|
||||
eofEvent.Close();
|
||||
eofEvent = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal void BeginReadLine()
|
||||
{
|
||||
if (cancelOperation)
|
||||
{
|
||||
cancelOperation = false;
|
||||
}
|
||||
if (sb == null)
|
||||
{
|
||||
sb = new StringBuilder(1024);
|
||||
stream.BeginRead(byteBuffer, 0, byteBuffer.Length, new AsyncCallback(ReadBuffer), null);
|
||||
return;
|
||||
}
|
||||
FlushMessageQueue();
|
||||
}
|
||||
|
||||
internal void CancelOperation()
|
||||
{
|
||||
cancelOperation = true;
|
||||
}
|
||||
|
||||
private void ReadBuffer(IAsyncResult ar)
|
||||
{
|
||||
int num;
|
||||
try
|
||||
{
|
||||
num = stream.EndRead(ar);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
num = 0;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
num = 0;
|
||||
}
|
||||
if (num == 0)
|
||||
{
|
||||
lock (messageQueue)
|
||||
{
|
||||
if (sb.Length != 0)
|
||||
{
|
||||
messageQueue.Enqueue(sb.ToString());
|
||||
sb.Length = 0;
|
||||
}
|
||||
messageQueue.Enqueue(null);
|
||||
}
|
||||
try
|
||||
{
|
||||
FlushMessageQueue();
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
eofEvent.Set();
|
||||
}
|
||||
}
|
||||
int chars = decoder.GetChars(byteBuffer, 0, num, charBuffer, 0);
|
||||
sb.Append(charBuffer, 0, chars);
|
||||
GetLinesFromStringBuilder();
|
||||
stream.BeginRead(byteBuffer, 0, byteBuffer.Length, new AsyncCallback(ReadBuffer), null);
|
||||
}
|
||||
|
||||
private void GetLinesFromStringBuilder()
|
||||
{
|
||||
int i = 0;
|
||||
int num = 0;
|
||||
int length = sb.Length;
|
||||
if (bLastCarriageReturn && length > 0 && sb[0] == '\n')
|
||||
{
|
||||
i = 1;
|
||||
num = 1;
|
||||
bLastCarriageReturn = false;
|
||||
}
|
||||
while (i < length)
|
||||
{
|
||||
char c = sb[i];
|
||||
if (c == '\r' || c == '\n')
|
||||
{
|
||||
if (c == '\r' && i + 1 < length && sb[i + 1] == '\n')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
string obj = sb.ToString(num, i + 1 - num);
|
||||
|
||||
num = i + 1;
|
||||
|
||||
lock (messageQueue)
|
||||
{
|
||||
messageQueue.Enqueue(obj);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Flush Fix: Send Whatever is left in the buffer
|
||||
string endOfBuffer = sb.ToString(num, length - num);
|
||||
lock (messageQueue)
|
||||
{
|
||||
messageQueue.Enqueue(endOfBuffer);
|
||||
num = length;
|
||||
}
|
||||
// End Flush Fix
|
||||
|
||||
if (sb[length - 1] == '\r')
|
||||
{
|
||||
bLastCarriageReturn = true;
|
||||
}
|
||||
if (num < length)
|
||||
{
|
||||
sb.Remove(0, num);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Length = 0;
|
||||
}
|
||||
FlushMessageQueue();
|
||||
}
|
||||
|
||||
private void FlushMessageQueue()
|
||||
{
|
||||
while (messageQueue.Count > 0)
|
||||
{
|
||||
lock (messageQueue)
|
||||
{
|
||||
if (messageQueue.Count > 0)
|
||||
{
|
||||
string data = (string)messageQueue.Dequeue();
|
||||
if (!cancelOperation)
|
||||
{
|
||||
userCallBack(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void WaitUtilEOF()
|
||||
{
|
||||
if (eofEvent != null)
|
||||
{
|
||||
eofEvent.WaitOne();
|
||||
eofEvent.Close();
|
||||
eofEvent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DataReceivedEventArgs : EventArgs
|
||||
{
|
||||
internal string _data;
|
||||
|
||||
/// <summary>Gets the line of characters that was written to a redirected <see cref="T:System.Diagnostics.Process" /> output stream.</summary>
|
||||
/// <returns>The line that was written by an associated <see cref="T:System.Diagnostics.Process" /> to its redirected <see cref="P:System.Diagnostics.Process.StandardOutput" /> or <see cref="P:System.Diagnostics.Process.StandardError" /> stream.</returns>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
public string Data => _data;
|
||||
|
||||
internal DataReceivedEventArgs(string data)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
<ApplicationIcon />
|
||||
<OutputType>Exe</OutputType>
|
||||
<StartupObject />
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user