diff --git a/Qrakhen.Qamp.Core/Benchmark.cs b/Qrakhen.Qamp.Core/Benchmark.cs index 5b3797d..9d208a3 100644 --- a/Qrakhen.Qamp.Core/Benchmark.cs +++ b/Qrakhen.Qamp.Core/Benchmark.cs @@ -33,14 +33,14 @@ public static class Benchmark if (!_clocks.TryGetValue(key, out Stopwatch? sw)) { sw = _clocks[key] = new Stopwatch(); - IO.Console.Write($" ::: Registered new benchmark clock '{key}'\n"); + IO.Console.Write($" ::: Registered new benchmark clock '{key}'"); } if (!string.IsNullOrEmpty(message)) - IO.Console.Write($" ::: {key}:{line} > {message}\n"); + IO.Console.Write($" ::: {key}:{line} > {message}"); if (sw.IsRunning) - IO.Console.Write($" ::: {key}:{line} > already running with an elapsed time of {sw.Elapsed}. clock was reset.\n"); + IO.Console.Write($" ::: {key}:{line} > already running with an elapsed time of {sw.Elapsed}. clock was reset."); sw.Reset(); sw.Start(); diff --git a/Qrakhen.Qamp.Core/Console.cs b/Qrakhen.Qamp.Core/Console.cs index 46f90fa..04b1bb3 100644 --- a/Qrakhen.Qamp.Core/Console.cs +++ b/Qrakhen.Qamp.Core/Console.cs @@ -1,20 +1,61 @@ -namespace Qrakhen.Qamp.Core.IO; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace Qrakhen.Qamp.Core.IO; public static class Console { - // TEMP - public static Action? StdOut; - // TEMP + public static OutputStreamMessageHandler StdOut; + public static ErrorStreamMessageHandler StdErr; + public static InputStreamListenHandler StdIn; + public static MessageFormatter Formatter; - public static void Write(object? any) + static Console() { - string[] split = $"{any ?? "null"}".Split('\n'); - for (int i = 0; i < split.Length; i++) { - string line = (i == 0 ? " :> " : " ") + $"{split[i]}\n"; - if (StdOut == null) - System.Console.Write(line); - else - StdOut(line); - } + StdOut = System.Console.Out.WriteLine; + StdErr = System.Console.Error.WriteLine; + StdIn = System.Console.In.ReadLine; + Formatter = (p) => { + if (p.Length == 0) + return []; + return p + .Select(v => $"{v}".Split('\n')) + .Select(v => string.Join($"\n :> ", v)) + .Select(v => $" :> {v}") + .ToArray(); + }; } -} \ No newline at end of file + + public static void Write(params object[] parameters) + { + if (StdOut == null) + return; + + var lines = Formatter(parameters); + foreach (var line in lines) + StdOut(line); + } + + public static string? Read() + { + if (StdIn == null) + throw new InvalidOperationException($"No stdin provided, can not read input stream."); + + return StdIn(); + } + + public static void Error(params object[] parameters) + { + if (StdErr == null) + Write(parameters); + + var lines = Formatter(parameters); + foreach (var line in lines) + StdErr(line); + } +} + +public delegate string? InputStreamListenHandler(); +public delegate void OutputStreamMessageHandler(string? message); +public delegate void ErrorStreamMessageHandler(string? message); + +public delegate string[] MessageFormatter(params object[] parameters); \ No newline at end of file diff --git a/Qrakhen.Qamp.Core/Execution/Runner.cs b/Qrakhen.Qamp.Core/Execution/Runner.cs index 5bc2d68..68e7cb7 100644 --- a/Qrakhen.Qamp.Core/Execution/Runner.cs +++ b/Qrakhen.Qamp.Core/Execution/Runner.cs @@ -48,7 +48,8 @@ public class Runner : IDisposable Options = options; Calls = new StackLike(options.MaxCalls); Stack = new StackLike(options.InitialStackSize); - IO.Console.StdOut = options.StdOut; + IO.Console.StdOut ??= options.StdOut; + IO.Console.StdIn ??= options.StdIn; } public ExecutionResult Run(Stream stream) @@ -62,15 +63,20 @@ public class Runner : IDisposable #endif Stack = new StackLike(Options.InitialStackSize); } + Benchmark.Start($"Compile Start"); using Reader reader = new Reader(stream); Compilation.Digester digester = new(reader); Function function = digester.Digest(); + Benchmark.End($"Compile End"); if (stream.Length > 64) File.WriteAllBytes($"./func.{DateTime.Now:yyyyMMdd_HHmmss}.sqi", function.Serialize(true)); Context closure = new Context(function); Push(Obj.Create(closure)); Invoke(closure, 0); - return Execute(); + Benchmark.Start($"Execution Start"); + ExecutionResult result = Execute(); + Benchmark.End($"Execution End"); + return result; } private bool TestFlag(Op code, Op flag) => (code & Op.F_Mask) == flag; @@ -681,14 +687,14 @@ public enum ExecutionResult } public readonly struct Options( - Action? stdOut = null, - Action? stdIn = null, + IO.OutputStreamMessageHandler stdOut = null, + IO.InputStreamListenHandler stdIn = null, int maxCalls = 0x100, int stackSize = 0x200, int initialStackSize = 0x80) { - public readonly Action? StdOut = stdOut; - public readonly Action? StdIn = stdIn; + public readonly IO.OutputStreamMessageHandler StdOut = stdOut; + public readonly IO.InputStreamListenHandler StdIn = stdIn; public readonly int MaxCalls = maxCalls; public readonly int StackSize = stackSize; public readonly int InitialStackSize = initialStackSize;