From 1da47d39dd2059daaefa5773801efb0512a6a772 Mon Sep 17 00:00:00 2001 From: Qrakhen Date: Fri, 8 May 2026 00:54:08 +0200 Subject: [PATCH] make this work under linux lol --- LICENSE.txt | 2 +- Qrakhen.Qamp.CLI/ConsoleColors.cs | 27 +++++ Qrakhen.Qamp.CLI/Program.cs | 105 +++++++++++++++++- Qrakhen.Qamp.CLI/Qrakhen.Qamp.CLI.csproj | 2 +- Qrakhen.Qamp.CLI/test.qp | 14 +++ Qrakhen.Qamp.Core.Tests/CodeTest.cs | 24 ++++ .../Qrakhen.Qamp.Core.Tests.csproj | 6 +- Qrakhen.Qamp.Core.Tests/UnitTest1.cs | 10 -- Qrakhen.Qamp.Core/Compilation/Digester.cs | 1 - Qrakhen.Qamp.Core/Execution/Runner.cs | 75 ++++++++++--- Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj | 2 +- Qrakhen.Qamp.Core/Values/ExtensionMethod.cs | 8 +- .../Qrakhen.Qamp.Digest.csproj | 2 +- .../Qrakhen.Qamp.Editor.csproj | 2 +- .../Qrakhen.Qamp.Memory.csproj | 2 +- .../Qrakhen.Qamp.Reader.csproj | 2 +- .../Qrakhen.Qamp.Runtime.csproj | 2 +- Qrakhen.Qamp.Tests/Qrakhen.Qamp.Tests.csproj | 2 +- debug | 5 + 19 files changed, 251 insertions(+), 42 deletions(-) create mode 100644 Qrakhen.Qamp.CLI/ConsoleColors.cs create mode 100644 Qrakhen.Qamp.CLI/test.qp create mode 100644 Qrakhen.Qamp.Core.Tests/CodeTest.cs delete mode 100644 Qrakhen.Qamp.Core.Tests/UnitTest1.cs create mode 100755 debug diff --git a/LICENSE.txt b/LICENSE.txt index 82116ad..21ea39a 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -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 diff --git a/Qrakhen.Qamp.CLI/ConsoleColors.cs b/Qrakhen.Qamp.CLI/ConsoleColors.cs new file mode 100644 index 0000000..2f3bc7c --- /dev/null +++ b/Qrakhen.Qamp.CLI/ConsoleColors.cs @@ -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; } +} \ No newline at end of file diff --git a/Qrakhen.Qamp.CLI/Program.cs b/Qrakhen.Qamp.CLI/Program.cs index da1d7f0..6af5ae2 100644 --- a/Qrakhen.Qamp.CLI/Program.cs +++ b/Qrakhen.Qamp.CLI/Program.cs @@ -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 Ignored = [ '\0', '\b' ]; +Benchmark.Active = false; LoggerService.Default = LogLevel.Error; List 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= \n", stdOut); + write(" -d --dialect=\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 { diff --git a/Qrakhen.Qamp.CLI/Qrakhen.Qamp.CLI.csproj b/Qrakhen.Qamp.CLI/Qrakhen.Qamp.CLI.csproj index 82e16ac..6c86437 100644 --- a/Qrakhen.Qamp.CLI/Qrakhen.Qamp.CLI.csproj +++ b/Qrakhen.Qamp.CLI/Qrakhen.Qamp.CLI.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 enable enable ..\Build\ diff --git a/Qrakhen.Qamp.CLI/test.qp b/Qrakhen.Qamp.CLI/test.qp new file mode 100644 index 0000000..48468ca --- /dev/null +++ b/Qrakhen.Qamp.CLI/test.qp @@ -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." \ No newline at end of file diff --git a/Qrakhen.Qamp.Core.Tests/CodeTest.cs b/Qrakhen.Qamp.Core.Tests/CodeTest.cs new file mode 100644 index 0000000..59d7879 --- /dev/null +++ b/Qrakhen.Qamp.Core.Tests/CodeTest.cs @@ -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); + + } +} diff --git a/Qrakhen.Qamp.Core.Tests/Qrakhen.Qamp.Core.Tests.csproj b/Qrakhen.Qamp.Core.Tests/Qrakhen.Qamp.Core.Tests.csproj index 08440ef..3de30da 100644 --- a/Qrakhen.Qamp.Core.Tests/Qrakhen.Qamp.Core.Tests.csproj +++ b/Qrakhen.Qamp.Core.Tests/Qrakhen.Qamp.Core.Tests.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable false @@ -15,6 +15,10 @@ + + + + diff --git a/Qrakhen.Qamp.Core.Tests/UnitTest1.cs b/Qrakhen.Qamp.Core.Tests/UnitTest1.cs deleted file mode 100644 index cd49e0d..0000000 --- a/Qrakhen.Qamp.Core.Tests/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Qrakhen.Qamp.Core.Tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - - } -} diff --git a/Qrakhen.Qamp.Core/Compilation/Digester.cs b/Qrakhen.Qamp.Core/Compilation/Digester.cs index 3118224..7f685dd 100644 --- a/Qrakhen.Qamp.Core/Compilation/Digester.cs +++ b/Qrakhen.Qamp.Core/Compilation/Digester.cs @@ -76,7 +76,6 @@ public class Digester : ISteppable public Function Digest() { - Benchmark.Active = true; Benchmark.Start($"Digest begin"); #if LOG _logger.Method(); diff --git a/Qrakhen.Qamp.Core/Execution/Runner.cs b/Qrakhen.Qamp.Core/Execution/Runner.cs index b80fcdd..f0e66a8 100644 --- a/Qrakhen.Qamp.Core/Execution/Runner.cs +++ b/Qrakhen.Qamp.Core/Execution/Runner.cs @@ -77,6 +77,8 @@ public class Runner : IDisposable private readonly ILogger _logger = LoggerService.Get(); private readonly OperationRouter _router = new OperationRouter(); + private Value _runnerReturned = Value.Void; + public readonly Options Options; private List _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 + _logger.Method(); + 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(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 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( diff --git a/Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj b/Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj index ec0b452..a8e5489 100644 --- a/Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj +++ b/Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable true diff --git a/Qrakhen.Qamp.Core/Values/ExtensionMethod.cs b/Qrakhen.Qamp.Core/Values/ExtensionMethod.cs index 828a74f..ab6ec7b 100644 --- a/Qrakhen.Qamp.Core/Values/ExtensionMethod.cs +++ b/Qrakhen.Qamp.Core/Values/ExtensionMethod.cs @@ -223,13 +223,19 @@ public static class StringExtensions public static long IndexOf(Value self, Value needle) { string _self = self.Ptr.As()?.Value ?? ""; - string _needle = self.Ptr.As()?.Value ?? ""; + string _needle = needle.Ptr.As()?.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()?.SubString(start, length) ?? Value.Void; + } + [ExtensionMethod] public static Objects.Array Split(Value self, Value splitter) { diff --git a/Qrakhen.Qamp.Digest/Qrakhen.Qamp.Digest.csproj b/Qrakhen.Qamp.Digest/Qrakhen.Qamp.Digest.csproj index f2f434b..705f905 100644 --- a/Qrakhen.Qamp.Digest/Qrakhen.Qamp.Digest.csproj +++ b/Qrakhen.Qamp.Digest/Qrakhen.Qamp.Digest.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable ..\Build\ diff --git a/Qrakhen.Qamp.Editor/Qrakhen.Qamp.Editor.csproj b/Qrakhen.Qamp.Editor/Qrakhen.Qamp.Editor.csproj index 1b30255..9cdd10d 100644 --- a/Qrakhen.Qamp.Editor/Qrakhen.Qamp.Editor.csproj +++ b/Qrakhen.Qamp.Editor/Qrakhen.Qamp.Editor.csproj @@ -2,7 +2,7 @@ WinExe - net8.0-windows + net10.0-windows enable enable true diff --git a/Qrakhen.Qamp.Memory/Qrakhen.Qamp.Memory.csproj b/Qrakhen.Qamp.Memory/Qrakhen.Qamp.Memory.csproj index 9093267..a786704 100644 --- a/Qrakhen.Qamp.Memory/Qrakhen.Qamp.Memory.csproj +++ b/Qrakhen.Qamp.Memory/Qrakhen.Qamp.Memory.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable ..\Build\ diff --git a/Qrakhen.Qamp.Reader/Qrakhen.Qamp.Reader.csproj b/Qrakhen.Qamp.Reader/Qrakhen.Qamp.Reader.csproj index 9093267..a786704 100644 --- a/Qrakhen.Qamp.Reader/Qrakhen.Qamp.Reader.csproj +++ b/Qrakhen.Qamp.Reader/Qrakhen.Qamp.Reader.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable ..\Build\ diff --git a/Qrakhen.Qamp.Runtime/Qrakhen.Qamp.Runtime.csproj b/Qrakhen.Qamp.Runtime/Qrakhen.Qamp.Runtime.csproj index d0afaed..8394389 100644 --- a/Qrakhen.Qamp.Runtime/Qrakhen.Qamp.Runtime.csproj +++ b/Qrakhen.Qamp.Runtime/Qrakhen.Qamp.Runtime.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable True diff --git a/Qrakhen.Qamp.Tests/Qrakhen.Qamp.Tests.csproj b/Qrakhen.Qamp.Tests/Qrakhen.Qamp.Tests.csproj index 9c5b30a..56bc533 100644 --- a/Qrakhen.Qamp.Tests/Qrakhen.Qamp.Tests.csproj +++ b/Qrakhen.Qamp.Tests/Qrakhen.Qamp.Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable diff --git a/debug b/debug new file mode 100755 index 0000000..053d0ea --- /dev/null +++ b/debug @@ -0,0 +1,5 @@ +#!/bin/bash + +DEST='net10.0' +echo "\e[5mBeelding for dotnet version $DEST like it's not a big deal.\e[0m" +dotnet build ./Qrakhen.Qamp.CLI/ && ./Build/Debug/net10.0/Qrakhen.Qamp.CLI -i ./Qrakhen.Qamp.CLI/test.qp