using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Reflection; using NTERA.Core.Interop; using NTERA.Engine.Compiler; namespace NTERA.Engine.Runtime.Base { public static class Keywords { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] private class KeywordAttribute : Attribute { public string Name { get; } public bool ImplicitString { get; } public bool ImplicitFormatted { get; } public KeywordAttribute(string name, bool implicitString = false, bool implicitFormatted = false) { if (implicitFormatted && !implicitString) throw new ArgumentException("Keyword cannot support formatting if it does not use implicit strings"); Name = name; ImplicitString = implicitString; ImplicitFormatted = implicitFormatted; } } public static Dictionary> StaticKeywords { get; } = _getKeywords(); private static Dictionary> _getKeywords() { var output = new Dictionary>(); foreach (MethodInfo method in typeof(Keywords).GetMethods(BindingFlags.Public | BindingFlags.Static)) { var keywords = method.GetCustomAttributes(); foreach (KeywordAttribute keyword in keywords) output[keyword.Name] = (runtime, context, node) => { method.Invoke(null, new object[] { runtime, context, node }); }; } return output; } [Keyword("TIMES")] public static void Times(EraRuntime runtime, StackFrame context, ExecutionNode node) { Variable variable = runtime.ComputeVariable(context, node[0], out var index); variable[index] *= runtime.ComputeExpression(context, node[1]); } [Keyword("VARSIZE")] public static void Varsize(EraRuntime runtime, StackFrame context, ExecutionNode node) { Variable variable = runtime.ComputeVariable(context, node[0], out var index); int maxArrayDimensions = variable.Max(x => x.Key.Length); var resultVariable = runtime.GlobalVariables["RESULT"]; for (int i = 0; i < maxArrayDimensions; i++) { resultVariable[i] = variable.Where(x => x.Key.Length > i).Max(x => x.Key[i]) + 1; } } [Keyword("ALIGNMENT")] public static void Alignment(EraRuntime runtime, StackFrame context, ExecutionNode node) { string alignmentType = runtime.ComputeExpression(context, node[0]).String; if (!Enum.TryParse(alignmentType, true, out DisplayLineAlignment alignmentValue)) throw new EraRuntimeException($"Unable to parse alignment type: '{alignmentType}'"); runtime.Console.Alignment = alignmentValue; } [Keyword("SETCOLOR")] public static void SetColor(EraRuntime runtime, StackFrame context, ExecutionNode node) { if (node.SubNodes.Length == 1) { uint argb = (uint)runtime.ComputeExpression(context, node[0]).Real; argb |= 0xFF000000U; Color c = Color.FromArgb((int)argb); runtime.Console.SetStringStyle(c); } else if (node.SubNodes.Length == 3) { int r = (int)runtime.ComputeExpression(context, node[0]).Real; int g = (int)runtime.ComputeExpression(context, node[1]).Real; int b = (int)runtime.ComputeExpression(context, node[2]).Real; runtime.Console.SetStringStyle(Color.FromArgb(r, g, b)); } else throw new EraRuntimeException("Unable to parse color"); } [Keyword("RESETCOLOR")] public static void ResetColor(EraRuntime runtime, StackFrame context, ExecutionNode node) { runtime.Console.ResetStyle(); } [Keyword("DRAWLINE")] public static void DrawLine(EraRuntime runtime, StackFrame context, ExecutionNode node) { runtime.Console.PrintBar(); } [Keyword("DRAWLINEFORM", true, true)] public static void DrawLineForm(EraRuntime runtime, StackFrame context, ExecutionNode node) { var value = runtime.ComputeExpression(context, node.Single()); runtime.Console.printCustomBar(value.ToString()); } [Keyword("PRINT_IMG")] public static void PrintImg(EraRuntime runtime, StackFrame context, ExecutionNode node) { var value = runtime.ComputeExpression(context, node.Single()); runtime.Console.PrintImg(value.ToString()); } [Keyword("PRINTBUTTON")] public static void PrintButton(EraRuntime runtime, StackFrame context, ExecutionNode node) { var textValue = runtime.ComputeExpression(context, node[0]); var intValue = runtime.ComputeExpression(context, node[1]); runtime.Console.PrintButton(textValue.String, (long)intValue.Real); } [Keyword("HTML_PRINT")] public static void PrintHtml(EraRuntime runtime, StackFrame context, ExecutionNode node) { var htmlValue = runtime.ComputeExpression(context, node.Single()); runtime.Console.PrintHtml(htmlValue.String, false); } [Keyword("PRINT", true, false)] [Keyword("PRINTFORM", true, true)] public static void Print(EraRuntime runtime, StackFrame context, ExecutionNode node) { var value = runtime.ComputeExpression(context, node.Single()); runtime.Console.Write(value.ToString()); } [Keyword("PRINTFORML", true, true)] [Keyword("PRINTL", true, false)] public static void PrintLine(EraRuntime runtime, StackFrame context, ExecutionNode node) { var value = runtime.ComputeExpression(context, node.Single()); runtime.Console.PrintSingleLine(value.ToString()); } } }