diff --git a/.gitignore b/.gitignore index 4ef5a95..1f3a57a 100644 --- a/.gitignore +++ b/.gitignore @@ -428,3 +428,4 @@ FodyWeavers.xsd *.msm *.msp +src/.github/copilot-instructions.md diff --git a/src/cs-mic-cli.sln b/src/cs-mic-cli.sln new file mode 100644 index 0000000..1558fc0 --- /dev/null +++ b/src/cs-mic-cli.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.37328.6 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cs-mic-cli", "cs-mic-cli\cs-mic-cli.csproj", "{D241250D-97BC-4D1F-A3B4-8A084D72DA7C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D241250D-97BC-4D1F-A3B4-8A084D72DA7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D241250D-97BC-4D1F-A3B4-8A084D72DA7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D241250D-97BC-4D1F-A3B4-8A084D72DA7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D241250D-97BC-4D1F-A3B4-8A084D72DA7C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {198FC807-9454-4AF0-BA73-30DFE9A7F7E4} + EndGlobalSection +EndGlobal diff --git a/src/cs-mic-cli/Functions/PrintVariables.cs b/src/cs-mic-cli/Functions/PrintVariables.cs new file mode 100644 index 0000000..4431fda --- /dev/null +++ b/src/cs-mic-cli/Functions/PrintVariables.cs @@ -0,0 +1,65 @@ +using CSMic; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace cs_mic_cli.Functions +{ + internal class PrintVariables : ICodedFunction + { + public InputInterpreter Parent + { + get; + private set; + } + + public string Name + { + get + { + return "printvariables"; + } + } + + public IEnumerable ExpectedArguments + { + get + { + yield break; + } + + } + + public FunctionValue ReturnValue + { + get + { + return FunctionValue.NONE; + } + } + + public PrintVariables(InputInterpreter parent) + { + this.Parent = parent; + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + int variableIndex = 1; + foreach(var variable in this.Parent.Variables) + { + var displayValue = variable.Value ?? string.Empty; + if(variable.Type == VariableType.NumericArray && variable.Value != null) + { + displayValue = string.Format("[{0}]", string.Join(", ", (decimal[])variable.Value)); + } + + Console.WriteLine("{0}. {1} {2} = {3}", variableIndex++, variable.Type, variable.Name, displayValue); + } + + return FunctionValue.NONE; + } + } +} diff --git a/src/cs-mic-cli/Options.cs b/src/cs-mic-cli/Options.cs new file mode 100644 index 0000000..7859b45 --- /dev/null +++ b/src/cs-mic-cli/Options.cs @@ -0,0 +1,21 @@ +using CommandLine; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace cs_mic_cli +{ + internal class Options + { + [Option('v', "verbose", HelpText = "Displays error messages from the parser if a soft error occurs.")] + public bool Verbose { get; set; } + + [Option('i', "interactive", HelpText = "Starts an interactive session.")] + public bool Interactive { get; set; } + + [Value(0)] + public required IEnumerable Expression { get; set; } + } +} diff --git a/src/cs-mic-cli/Program.cs b/src/cs-mic-cli/Program.cs new file mode 100644 index 0000000..abed934 --- /dev/null +++ b/src/cs-mic-cli/Program.cs @@ -0,0 +1,77 @@ +using CommandLine; +using cs_mic_cli.Functions; +using CSMic; +using CSMic.StandardLibrary; + +namespace cs_mic_cli +{ + internal class Program + { + + static void Main(string[] args) + { + CommandLine.Parser.Default.ParseArguments(args) + .WithParsed(options => + { + var fullExpression = string.Join(' ', options.Expression); + var inputInterpreter = new InputInterpreter(); + + Initializer.InitializeAll(inputInterpreter); + inputInterpreter.RegisterFunction(new PrintVariables(inputInterpreter)); + + if(!options.Verbose) + { + CSMic.Interpreter.Errors.errorStream = TextWriter.Null; + } + + if (string.IsNullOrWhiteSpace(fullExpression) || options.Interactive) + { + // console mode + bool exitRequested = false; + + Console.CancelKeyPress += (_, e) => + { + e.Cancel = true; + exitRequested = true; + Console.WriteLine(); + }; + + while (!exitRequested) + { + Console.Write("csmic> "); + + fullExpression = Console.ReadLine(); + + if (string.IsNullOrWhiteSpace(fullExpression)) + { + Console.WriteLine(); + break; + } + + Calculate(inputInterpreter, options, fullExpression); + } + } + else + { + // one-shot mode + Calculate(inputInterpreter, options, fullExpression); + } + }) + .WithNotParsed(options => + { + + }); + } + + private static void Calculate(InputInterpreter inputInterpreter, Options options, string expression) + { + inputInterpreter.Interpret(expression); + + Console.WriteLine(inputInterpreter.NumericValue); + if(options.Verbose) + { + Console.WriteLine("Executed in {0:N2} ms | Variables: {1:N0}", inputInterpreter.LastExecutionTime.TotalMilliseconds, inputInterpreter.Variables.Count()); + } + } + } +} diff --git a/src/cs-mic-cli/cs-mic-cli.csproj b/src/cs-mic-cli/cs-mic-cli.csproj new file mode 100644 index 0000000..c888b75 --- /dev/null +++ b/src/cs-mic-cli/cs-mic-cli.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + cs_mic_cli + enable + enable + true + true + + + + + + + + +