Browse Source

New CoreExpression functions

Kenric Nugteren 4 months ago
parent
commit
12449feed9

+ 62 - 0
InABox.Core/Expression/ArrayFunctions.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+
+namespace InABox.Core
+{
+    internal static class ArrayFunctions
+    {
+        public const string GROUP = "Array";
+
+        public static void Register()
+        {
+            CoreExpression.RegisterFunction("Array", "Create a new array, with the given type and length.", GROUP, new[]
+            {
+                "string type", "int length"
+            }, (p, v, c) =>
+            {
+                var type = ConvertType(p[0].Evaluate<string>(v));
+                var length = p[1].Evaluate<int>(v);
+                return Array.CreateInstance(type, length);
+            });
+        }
+
+        private static readonly Dictionary<string, Type> _types = new Dictionary<string, Type>()
+        {
+            { "sbyte", typeof(sbyte) },
+            { "byte", typeof(byte) },
+            { "short", typeof(short) },
+            { "ushort", typeof(ushort) },
+            { "int", typeof(int) },
+            { "uint", typeof(uint) },
+            { "long", typeof(long) },
+            { "ulong", typeof(ulong) },
+
+            { "float", typeof(float) },
+            { "double", typeof(double) },
+            { "decimal", typeof(decimal) },
+
+            { "bool", typeof(bool) },
+            { "char", typeof(char) },
+            { "string", typeof(string) },
+
+            { "TimeSpan", typeof(TimeSpan) },
+            { "DateTime", typeof(DateTime) },
+        };
+
+        public static bool TryConvertType(string str, [NotNullWhen(true)] out Type? type)
+        {
+            if(_types.TryGetValue(str, out type)) return true;
+            type = Type.GetType(str);
+            if (type != null) return true;
+            return false;
+        }
+
+        public static Type ConvertType(string str)
+        {
+            if(TryConvertType(str, out var type)) return type;
+            throw new Exception($"Invalid type {str}");
+        }
+    }
+}

+ 67 - 3
InABox.Core/CoreExpression.cs → InABox.Core/Expression/CoreExpression.cs

@@ -9,6 +9,7 @@ using System.Linq;
 using System.Text;
 using System.Text.RegularExpressions;
 using Expressive.Exceptions;
+using Expressive.Operators;
 
 namespace InABox.Core
 {
@@ -21,14 +22,58 @@ namespace InABox.Core
         public abstract string Description { get; }
         public abstract string[] Parameters { get; }
     }
-    
+
+    public interface IExpressionConstant
+    {
+        string Name { get; set; }
+
+        object? GetValue();
+    }
+
+    public class CoreExpressionFunctor : CoreExpressionFunction
+    {
+        public delegate object? EvaluateDelegate(IExpression[] parameters, IDictionary<string, object?> variables, Context context);
+
+        public EvaluateDelegate Function { get; set; }
+
+        private string _name;
+        public override string Name => _name;
+
+        private string _description;
+        public override string Description => _description;
+
+        private string _group;
+        public override string Group => _group;
+
+        private string[] _parameters;
+        public override string[] Parameters => _parameters;
+
+        private int minParameters;
+
+        public CoreExpressionFunctor(EvaluateDelegate function, string name, string description, string group, string[] parameters, int? minParameters = null)
+        {
+            Function = function;
+            _name = name;
+            _description = description;
+            _group = group;
+            _parameters = parameters;
+            minParameters = minParameters ?? parameters.Length;
+        }
+
+        public override object? Evaluate(IExpression[] parameters, Context context)
+        {
+            ValidateParameterCount(parameters, _parameters.Length, minParameters);
+            return Function(parameters, Variables, context);
+        }
+    }
+
     internal class FormatFunction : CoreExpressionFunction
     {
         #region IFunction Members
 
         public override object Evaluate(IExpression[] parameters, Context context)
         {
-            ValidateParameterCount(parameters,-1, 2);
+            ValidateParameterCount(parameters, -1, 2);
 
             string fmt = parameters.First()?.Evaluate(Variables).ToString() ?? string.Empty;
             object[] objects = parameters.Skip(1).Select(x => x.Evaluate(Variables)).ToArray();
@@ -174,17 +219,27 @@ namespace InABox.Core
         
         private static Context _context = new Context(ExpressiveOptions.None);
         
-        static void RegisterFunction<T>() where T : CoreExpressionFunction, new ()
+        public static void RegisterFunction<T>() where T : CoreExpressionFunction, new ()
         {
             var function = new T();
             Functions.Add(function);
             _context.RegisterFunction(function);
         }
+
+        public static void RegisterFunction(string name, string description, string group, string[] parameters, CoreExpressionFunctor.EvaluateDelegate function)
+        {
+            var f = new CoreExpressionFunctor(function, name, description, group, parameters);
+            Functions.Add(f);
+            _context.RegisterFunction(f);
+        }
         
         static CoreExpression()
         {
             RegisterFunction<FormatFunction>();
             RegisterFunction<Client_LoadDocumentFunction>();
+
+            DateFunctions.Register();
+            ArrayFunctions.Register();
         }
 
         #endregion
@@ -242,4 +297,13 @@ namespace InABox.Core
             }
         }
     }
+
+    public static class CoreExpressionExtensions
+    {
+        public static T Evaluate<T>(this IExpression expression, IDictionary<string, object?>? variables)
+        {
+            var result = expression.Evaluate(variables);
+            return CoreUtils.ChangeType<T>(result);
+        }
+    }
 }

+ 17 - 0
InABox.Core/Expression/DateFunctions.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace InABox.Core
+{
+    internal static class DateFunctions
+    {
+        public const string GROUP = "Date";
+
+        public static void Register()
+        {
+            CoreExpression.RegisterFunction("Now", "Returns the current date and time.", GROUP, new string[] {}, (p, vars, c) => DateTime.Now);
+            CoreExpression.RegisterFunction("Today", "Returns the current date.", GROUP, new string[] {}, (p, vars, c) => DateTime.Today);
+        }
+    }
+}