diff --git a/.gitignore b/.gitignore index cd0982a..0babe19 100644 --- a/.gitignore +++ b/.gitignore @@ -542,5 +542,3 @@ FodyWeavers.xsd # End of https://www.toptal.com/developers/gitignore/api/rider,visualbasic,visualstudio # Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) - -*.glyph diff --git a/GlobalUsing.cs b/GlobalUsing.cs index 4d883b0..20fb182 100644 --- a/GlobalUsing.cs +++ b/GlobalUsing.cs @@ -1 +1,5 @@ global using Glyph; +global using CliFx; +global using CliFx.Attributes; +global using CliFx.Infrastructure; +global using System.IO; diff --git a/Glyph.csproj b/Glyph.csproj index 49c8395..b0278aa 100644 --- a/Glyph.csproj +++ b/Glyph.csproj @@ -4,11 +4,13 @@ Exe net8.0 enable + glyph enable 0.1.100 + diff --git a/Program.cs b/Program.cs index 7dcf62f..c55e416 100644 --- a/Program.cs +++ b/Program.cs @@ -1,10 +1,4 @@ -string[] code = new[] -{ - "# Skip this line", - "set x 5", - "mul x 2", - "say x", - "end" -}; - -Runner.Interpret(code); +await new CliApplicationBuilder() + .AddCommand() + .Build() + .RunAsync(); diff --git a/README.md b/README.md index 78bdcdb..879cdd7 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,36 @@ verb subject object [modifier] | `mod` | modulo | `mod x 5` | | `end` | stop execution | `end` | -## 📜 License +## 🧩 Tech Stack + +- .NET 8.0 +- Dynamic Expresso for interpreter + +## 🗓️ Update Cycle + +| Type | Frequency | Notes | +| ------------ | ---------------- | ---------------------------------------- | +| Minor Update | Every 3–6 months | Small enhancements, non-breaking changes | +| Patch Update | As needed | Bug fixes, security updates | +| Major Update | As needed | Framework upgrades, major refactors | + +- Reserve months: June (Mid-Year Chill) & December (End-Year Freeze) + +## 🛡️ Status + +- [x] Active Support +- [ ] Limited Support (Security patches only) +- [ ] Maintenance Mode (Dependency-only updates) +- [ ] Archived (No active work planned) + +## 🎮 Relaxation Practices + +- 20% creative/recovery space built into development +- Mandatory cooldowns after major launches (minimum 1 week) +- Crisis Mode Activates if: + - Critical vulnerabilities + - Framework-breaking issues + +## 🗒️ License I license this project under the GPL v3 license - see [LICENSE](LICENSE) for details. diff --git a/RunCommand.cs b/RunCommand.cs new file mode 100644 index 0000000..509b854 --- /dev/null +++ b/RunCommand.cs @@ -0,0 +1,51 @@ +namespace Glyph; + +[Command("run", Description = "Run a Glyph program.")] +public class RunCommand : ICommand +{ + [CommandParameter(0, Name = "file", Description = "Path to the Glyph source file.")] + public string FilePath { get; set; } + + [CommandOption("input", 'i', Description = "Path to optional input file.")] + public string InputPath { get; set; } + + [CommandOption("binary", 'b', Description = "Run binary file")] + public bool Binary { get; set; } + + [CommandOption("verbose", 'v', Description = "Enable verbose output.")] + public bool Verbose { get; set; } + + public async ValueTask ExecuteAsync(IConsole console) + { + var lines = new string[] { }; + + if (!System.IO.File.Exists(FilePath)) + { + await console.Error.WriteLineAsync($"Error: File not found: {FilePath}"); + return; + } + + if (Binary) + { + // TODO: Implement binary file execution + await console.Error.WriteLineAsync($"Error: Binary file execution not implemented"); + return; + } + + lines = await System.IO.File.ReadAllLinesAsync(FilePath); + + if (!string.IsNullOrEmpty(InputPath)) + { + // You could inject input to the interpreter here + string input = await File.ReadAllTextAsync(InputPath); + // TODO: Attach to interpreter input stream + } + + if (Verbose) + { + await console.Output.WriteLineAsync($"Executing: {FilePath}"); + } + + Runner.Interpret(lines); + } +} diff --git a/Runner.cs b/Runner.cs index c88085f..4443316 100644 --- a/Runner.cs +++ b/Runner.cs @@ -8,8 +8,8 @@ public static class Runner { var env = new Dictionary(); var labels = new Dictionary(); - var callStack = new Stack(); - var interpreter = new Interpreter(); + var stack = new Stack(); + var exp = new Interpreter(); int pc = 0; // First pass: record labels @@ -40,8 +40,8 @@ public static class Runner object Eval(string expr) { foreach (var (k, v) in env) - interpreter.SetVariable(k, v); - return interpreter.Eval(expr); + exp.SetVariable(k, v); + return exp.Eval(expr); } switch (cmd) @@ -101,7 +101,7 @@ public static class Runner case "call": if (arg1 != null && labels.TryGetValue(arg1, out var fnStart)) { - callStack.Push(pc); + stack.Push(pc); pc = fnStart + 1; if (arg2 != null) env["x"] = Eval(arg2); @@ -109,8 +109,8 @@ public static class Runner break; case "ret": - if (callStack.Count > 0) - pc = callStack.Pop(); + if (stack.Count > 0) + pc = stack.Pop(); else return; break; diff --git a/ScriptHelper.cs b/ScriptHelper.cs new file mode 100644 index 0000000..6b5f956 --- /dev/null +++ b/ScriptHelper.cs @@ -0,0 +1,18 @@ +namespace Glyph; + +public static class ScriptHelper +{ + /// + /// Encodes a string to Base64. + /// + /// The string to encode. + /// The Base64 encoded string. + // https://arcanecode.com/2007/03/21/encoding-strings-to-base64-in-c/ + static public string EncodeTo64(string toEncode) + { + byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode); + string returnValue = System.Convert.ToBase64String(toEncodeAsBytes); + return returnValue; + + } +} diff --git a/sample.glif b/sample.glif new file mode 100644 index 0000000..3146d31 --- /dev/null +++ b/sample.glif @@ -0,0 +1,4 @@ +set x 5 +mul x 2 +say x +end