make this work under linux lol
This commit is contained in:
parent
44b8bb8900
commit
1da47d39dd
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) [2025] [David Neumaier, Qrakhen]
|
||||
Copyright (c) [2026] [David Neumaier, Qrakhen]
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
namespace Qrakhen.Qamp.CLI;
|
||||
|
||||
[Flags]
|
||||
public enum ConsoleMods
|
||||
{
|
||||
None = 0,
|
||||
|
||||
Red = 1,
|
||||
Green = 2,
|
||||
Blue = 4,
|
||||
|
||||
Yellow = Red | Green,
|
||||
White = Red | Green | Blue,
|
||||
|
||||
|
||||
|
||||
Color = 1 << 10,
|
||||
Bold = 1 << 20,
|
||||
Italic = 1 << 21,
|
||||
Underlined = 1 << 22,
|
||||
Clear = 1 << 31,
|
||||
}
|
||||
|
||||
public interface IConsolePainter
|
||||
{
|
||||
ConsoleMods Mods { get; set; }
|
||||
}
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
using Qrakhen.Qamp.Core;
|
||||
using Qrakhen.Qamp.Core.Execution;
|
||||
using Qrakhen.Qamp.Core.Logging;
|
||||
using System.Drawing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
|
||||
List<char> Ignored = [ '\0', '\b' ];
|
||||
Benchmark.Active = false;
|
||||
LoggerService.Default = LogLevel.Error;
|
||||
List<byte[]> History = [];
|
||||
int historyCursor = -1;
|
||||
|
|
@ -12,10 +16,59 @@ bool useSyntaxHighlighting = false;
|
|||
(int x, int y) cursor = (0, 0);
|
||||
ConsoleCode code = ConsoleCode.Error;
|
||||
Runner runner = new(new Options());
|
||||
Stream stdOut = Console.OpenStandardOutput();
|
||||
Stream stdErr = Console.OpenStandardError();
|
||||
Stream stdIn = Console.OpenStandardInput();
|
||||
|
||||
void write(string what, Stream stream) => stream.Write(Encoding.Default.GetBytes(what));
|
||||
|
||||
string[] flags = args.Where(x => x.StartsWith("-")).Select(x => x[1..]).ToArray();
|
||||
string[] files = args.Where(x => !x.StartsWith("-")).ToArray();
|
||||
|
||||
if (flags.IndexOf("h") > 0)
|
||||
{
|
||||
write(" :: Q& Help.\n", stdOut);
|
||||
write(" Basic usage: qamp {FILES} {OPTIONS}\n", stdOut);
|
||||
write(" Flags:\n", stdOut);
|
||||
write(" -i --interactive \n", stdOut);
|
||||
write(" -n --nurture \n", stdOut);
|
||||
write(" -l --log-level=<int> \n", stdOut);
|
||||
write(" -d --dialect=<sqr|default>\n", stdOut);
|
||||
write(" Example: qamp ~/myNiceScript.qp -i -n -l=0\n", stdOut);
|
||||
return (int)QRESULT.OK;
|
||||
}
|
||||
|
||||
if (files.Length > 0)
|
||||
{
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (File.Exists(file))
|
||||
{
|
||||
var result = runner.Run(File.OpenRead(file));
|
||||
write($" :: {file}: {result.RunnerResult} ({result.Returned})\n", stdOut);
|
||||
}
|
||||
else
|
||||
{
|
||||
write($"Could not find file located at '{file}'.\n", stdErr);
|
||||
return (int)QRESULT.NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags.IndexOf("i") < 0 && files.Length > 0)
|
||||
{
|
||||
return (int)QRESULT.OK;
|
||||
}
|
||||
|
||||
if (flags.IndexOf("i") < 0)
|
||||
{
|
||||
write(" :: Assuming interactive mode (-i).\n :: If that is intended, use qamp -i to prevent this notification.\n", stdOut);
|
||||
}
|
||||
|
||||
do {
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
MemoryStream stream = new MemoryStream();
|
||||
Console.Write(" <: ");
|
||||
write(" <: ", stdOut);
|
||||
cursor = Console.GetCursorPosition();
|
||||
do {
|
||||
if (useSyntaxHighlighting)
|
||||
|
|
@ -25,12 +78,22 @@ do {
|
|||
if (input.Modifiers == ConsoleModifiers.Control) {
|
||||
if (input.Key == ConsoleKey.H) {
|
||||
useSyntaxHighlighting = !useSyntaxHighlighting;
|
||||
Console.Write($"\n #: {nameof(useSyntaxHighlighting)} = {useSyntaxHighlighting}\n <: ");
|
||||
//write(Colors.ColorText($"\n #: {nameof(useSyntaxHighlighting)} = {useSyntaxHighlighting}\n <: ", 30));
|
||||
write($"\n #: {nameof(useSyntaxHighlighting)} = {useSyntaxHighlighting}\n <: ", stdOut);
|
||||
cursor = Console.GetCursorPosition();
|
||||
}
|
||||
|
||||
if (input.Key == ConsoleKey.B) {
|
||||
Benchmark.Active = !Benchmark.Active;
|
||||
//write(Colors.ColorText($"\n #: {nameof(Benchmark)}.{nameof(Benchmark.Active)} = {Benchmark.Active}\n <: ", 30));
|
||||
write($"\n #: {nameof(Benchmark)}.{nameof(Benchmark.Active)} = {Benchmark.Active}\n <: ", stdOut);
|
||||
cursor = Console.GetCursorPosition();
|
||||
}
|
||||
|
||||
if (input.Key == ConsoleKey.L) {
|
||||
LoggerService.Default = LoggerService.Default < LogLevel.All ? LogLevel.All : LogLevel.Info;
|
||||
Console.Write($"\n #: LogLevel = {LoggerService.Default}\n <: ");
|
||||
//write(Colors.ColorText($"\n #: LogLevel = {LoggerService.Default}\n <: ", 30));
|
||||
write($"\n #: LogLevel = {LoggerService.Default}\n <: ", stdOut);
|
||||
cursor = Console.GetCursorPosition();
|
||||
}
|
||||
continue;
|
||||
|
|
@ -106,6 +169,42 @@ do {
|
|||
}
|
||||
} while (code != ConsoleCode.Exit);
|
||||
|
||||
return (int)QRESULT.OK;
|
||||
|
||||
// yes i'm making these up, just like anyone else
|
||||
public enum QRESULT
|
||||
{
|
||||
OK = 0,
|
||||
INVALID_ARGS = 0x14,
|
||||
SYNTAX_ERROR = 0x72,
|
||||
NOT_FOUND = 0x204
|
||||
}
|
||||
|
||||
// leenux colors
|
||||
public static class Colors
|
||||
{
|
||||
private readonly static int cBlack = 0,
|
||||
cRed = 1,
|
||||
cGreen = 2,
|
||||
cYellow = 3,
|
||||
cCyan = 4,
|
||||
cPink = 5,
|
||||
cCyanD = 6,
|
||||
cWhite = 7;
|
||||
|
||||
private readonly static int fBack = 40,
|
||||
fFore = 30;
|
||||
|
||||
|
||||
private static string Wrap(int code) => @$"\e[{code}m";
|
||||
|
||||
// goote goute
|
||||
public static string ColorText(string text, params int[] codes) =>
|
||||
string.Join("", codes.Select(c => Wrap(c))) + text + Wrap(0);
|
||||
|
||||
public static string Red { get; } = Wrap(fFore + cRed);
|
||||
}
|
||||
|
||||
public class Command
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<BaseOutputPath>..\Build\</BaseOutputPath>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
print("\nQ& Test script.");
|
||||
|
||||
*~ how <~ 'very cool';
|
||||
var _WHAT_ = "ABQ&%$#@!";
|
||||
|
||||
var a = 7;
|
||||
*~ b <~ 12;
|
||||
var c <~ 8;
|
||||
*~ d = 3;
|
||||
|
||||
:: _WHAT_.SubString(2, 2) + ' is ' + how;
|
||||
print(a * b * c * d);
|
||||
|
||||
:: "if you can read this, Q& probably works. Wow."
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using System.Text;
|
||||
using Qrakhen.Qamp.Core.Execution;
|
||||
|
||||
namespace Qrakhen.Qamp.Core.Tests;
|
||||
|
||||
public class CodeTest
|
||||
{
|
||||
private readonly Runner _runner = new(new Options());
|
||||
|
||||
private RunnerResult ExecuteCode(string code)
|
||||
{
|
||||
using Stream stream = new MemoryStream();
|
||||
stream.Write(Encoding.UTF8.GetBytes(code));
|
||||
return _runner.Run(stream);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VariableDeclaration_Empty_AllocatesName()
|
||||
{
|
||||
string code = "var name;";
|
||||
var result = ExecuteCode(code);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
|
@ -15,6 +15,10 @@
|
|||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
namespace Qrakhen.Qamp.Core.Tests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -76,7 +76,6 @@ public class Digester : ISteppable<Token>
|
|||
|
||||
public Function Digest()
|
||||
{
|
||||
Benchmark.Active = true;
|
||||
Benchmark.Start($"Digest begin");
|
||||
#if LOG
|
||||
_logger.Method();
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ public class Runner : IDisposable
|
|||
private readonly ILogger _logger = LoggerService.Get<Runner>();
|
||||
private readonly OperationRouter _router = new OperationRouter();
|
||||
|
||||
private Value _runnerReturned = Value.Void;
|
||||
|
||||
public readonly Options Options;
|
||||
|
||||
private List<IOperationResolver> _resolvers = [];
|
||||
|
|
@ -103,36 +105,52 @@ public class Runner : IDisposable
|
|||
_router.Register(new ArithmeticResolver());
|
||||
}
|
||||
|
||||
public ExecutionResult Run(Stream stream)
|
||||
public ExecutionResult Run(Stream stream, params string[] parameters)
|
||||
{
|
||||
#if LOG
|
||||
_logger.Method();
|
||||
#endif
|
||||
|
||||
if (_stack.Position != 0) {
|
||||
#if LOG
|
||||
_logger.Warn($"Something went wrong, stack cursor is at {_stack.Position}. Resetting Stack.");
|
||||
#endif
|
||||
_logger.Warn($"Something went terribly wrong, stack cursor is at {_stack.Position} before execution.\n --- Resetting Stack ---");
|
||||
_stack = new StackLike<Value>(Options.InitialStackSize);
|
||||
}
|
||||
|
||||
DateTime start = DateTime.Now;
|
||||
Benchmark.Start($"Compile Start");
|
||||
|
||||
// cached value, used to directly return resulting values to the calling process
|
||||
_runnerReturned = Value.Void;
|
||||
|
||||
using Reader reader = new Reader(stream);
|
||||
Compilation.Digester digester = new(reader);
|
||||
Function function = digester.Digest();
|
||||
Benchmark.End($"Compile End");
|
||||
|
||||
// compilation result taste test
|
||||
if (stream.Length > 64)
|
||||
File.WriteAllBytes($"./func.{DateTime.Now:yyyyMMdd_HHmmss}.sqi", function.Serialize(true));
|
||||
|
||||
// run the code in a new context.
|
||||
// global namespace bleeds into here anyway, executing directly in global namespace is a 'safety risk'.
|
||||
Context closure = new Context(function);
|
||||
Push(Obj.Create(closure));
|
||||
Invoke(closure, 0);
|
||||
|
||||
Benchmark.Start($"Execution Start");
|
||||
ExecutionResult result = Execute();
|
||||
RunnerResult result = Execute();
|
||||
Benchmark.End($"Execution End");
|
||||
return result;
|
||||
|
||||
DateTime end = DateTime.Now;
|
||||
|
||||
return new ExecutionResult(result,
|
||||
_runnerReturned,
|
||||
start,
|
||||
end,
|
||||
parameters);
|
||||
}
|
||||
|
||||
private bool TestHandler(Op code, Op handler) => (code & Op.Mask_Handler) == handler;
|
||||
|
||||
private ExecutionResult Execute()
|
||||
private RunnerResult Execute()
|
||||
{
|
||||
#if LOG
|
||||
_logger.Method();
|
||||
|
|
@ -426,7 +444,7 @@ public class Runner : IDisposable
|
|||
} else {
|
||||
_logger.Warn($"Critical issue at end of execution detected - stack was empty at return.");
|
||||
}
|
||||
return ExecutionResult.OK;
|
||||
return RunnerResult.OK;
|
||||
}
|
||||
_stack.Decimate(call.StackPtr.Cursor);
|
||||
Push(result);
|
||||
|
|
@ -500,7 +518,7 @@ public class Runner : IDisposable
|
|||
|
||||
} while (call.Instruction.Segment.Instructions.Length > call.Instruction.Cursor);
|
||||
|
||||
return ExecutionResult.OK;
|
||||
return RunnerResult.OK;
|
||||
}
|
||||
|
||||
private Outer CaptureOuter(Pointer<Value> target)
|
||||
|
|
@ -684,7 +702,7 @@ public class Runner : IDisposable
|
|||
_stack.Push(value);
|
||||
}
|
||||
|
||||
private ExecutionResult Error(string message, object? context = null, bool @throw = true)
|
||||
private RunnerResult Error(string message, object? context = null, bool @throw = true)
|
||||
{
|
||||
#if LOG
|
||||
_logger.Method(message);
|
||||
|
|
@ -695,7 +713,7 @@ public class Runner : IDisposable
|
|||
Panic();
|
||||
if (@throw)
|
||||
throw new QampException(message, context);
|
||||
return ExecutionResult.Execution;
|
||||
return RunnerResult.Execution;
|
||||
}
|
||||
|
||||
private void Panic()
|
||||
|
|
@ -719,12 +737,35 @@ public class GarbageCollector
|
|||
|
||||
}
|
||||
|
||||
public enum ExecutionResult
|
||||
public enum RunnerResult
|
||||
{
|
||||
OK = 0x0000,
|
||||
Error = 0x1000,
|
||||
Compilation = Error | 0x0001,
|
||||
Execution = Error | 0x0002
|
||||
Compilation = 0x0001,
|
||||
Execution = 0x0002,
|
||||
|
||||
Unknown = -1
|
||||
}
|
||||
|
||||
public readonly struct ExecutionResult(
|
||||
RunnerResult code = RunnerResult.Unknown,
|
||||
Value? returned = null,
|
||||
DateTime? started = null,
|
||||
DateTime? finished = null,
|
||||
string[] parameters = null)
|
||||
{
|
||||
public RunnerResult RunnerResult { get; } = code;
|
||||
public Value? Returned { get; } = returned;
|
||||
|
||||
public DateTime Started { get; } = started ?? DateTime.Now;
|
||||
public DateTime Finished { get; } = finished ?? DateTime.Now;
|
||||
|
||||
public string[] Parameters { get; } = parameters ?? [];
|
||||
|
||||
public bool Success => RunnerResult == RunnerResult.OK;
|
||||
public bool HasValue => Returned?.Type != T.Void;
|
||||
|
||||
public TimeSpan Elapsed => Finished - Started;
|
||||
}
|
||||
|
||||
public readonly struct Options(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
|
|
|||
|
|
@ -223,13 +223,19 @@ public static class StringExtensions
|
|||
public static long IndexOf(Value self, Value needle)
|
||||
{
|
||||
string _self = self.Ptr.As<Objects.String>()?.Value ?? "";
|
||||
string _needle = self.Ptr.As<Objects.String>()?.Value ?? "";
|
||||
string _needle = needle.Ptr.As<Objects.String>()?.Value ?? "";
|
||||
if (_needle.Length < 1 || _self.Length < 1)
|
||||
return -1;
|
||||
|
||||
return _self.IndexOf(_needle);
|
||||
}
|
||||
|
||||
[ExtensionMethod]
|
||||
public static Value SubString(Value self, Value start, Value length)
|
||||
{
|
||||
return self.Ptr.As<Objects.String>()?.SubString(start, length) ?? Value.Void;
|
||||
}
|
||||
|
||||
[ExtensionMethod]
|
||||
public static Objects.Array Split(Value self, Value splitter)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<BaseOutputPath>..\Build\</BaseOutputPath>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<BaseOutputPath>..\Build\</BaseOutputPath>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<BaseOutputPath>..\Build\</BaseOutputPath>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue