Add system statements ('exc')

This commit is contained in:
Stone_Red
2022-05-24 19:49:25 +02:00
parent 3c98c2b26f
commit dd6fbf3be7
8 changed files with 461 additions and 1 deletions
+3
View File
@@ -64,6 +64,9 @@ dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case dotnet_naming_style.pascal_case.capitalization = pascal_case
# S1172: Unused method parameters should be removed
dotnet_diagnostic.S1172.severity = none
[*.{cs,vb}] [*.{cs,vb}]
#### Naming styles #### #### Naming styles ####
+15 -1
View File
@@ -12,26 +12,40 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.editorconfig = .editorconfig .editorconfig = .editorconfig
EndProjectSection EndProjectSection
EndProject 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{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}.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.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
{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.ActiveCfg = Debug|Any CPU
{E40573DB-912A-4871-BB65-3EE6E7D72E79}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{E40573DB-912A-4871-BB65-3EE6E7D72E79}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{2F95DCA7-3E43-4F2E-8FB2-067F0EC962B1}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -0,0 +1,12 @@
{
"profiles": {
"YesNt.CodeEditor": {
"commandName": "Project"
},
"WSL": {
"commandName": "WSL2",
"environmentVariables": {},
"distributionName": ""
}
}
}
+1
View File
@@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -5,6 +5,8 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <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);
}
}
}
+316
View File
@@ -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 /> <ApplicationIcon />
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<StartupObject /> <StartupObject />
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup> </PropertyGroup>
</Project> </Project>