CoreExpression.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using Expressive;
  2. using Expressive.Expressions;
  3. using Expressive.Functions;
  4. using InABox.Clients;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. namespace InABox.Core
  10. {
  11. using FncType = Func<IExpression[], IDictionary<string, object>, object?>;
  12. public interface IExpressionModel { }
  13. public interface IExpressionModel<TReturn> : IExpressionModel { }
  14. public class CoreExpression
  15. {
  16. private Expression Expression;
  17. public IReadOnlyCollection<string> ReferencedVariables => Expression.ReferencedVariables;
  18. protected virtual Type? ReturnType { get; }
  19. public CoreExpression(string expressionString)
  20. {
  21. Expression = new Expression(expressionString);
  22. foreach (var (name, function) in _functions)
  23. {
  24. Expression.RegisterFunction(name, function);
  25. }
  26. }
  27. public object? Evaluate(Dictionary<string, object?>? variables)
  28. {
  29. var result = Expression.Evaluate(variables);
  30. if(ReturnType != null)
  31. {
  32. return CoreUtils.ChangeType(result, ReturnType);
  33. }
  34. return result;
  35. }
  36. #region Static
  37. private static List<Tuple<string, FncType>> _functions = new List<Tuple<string, FncType>>();
  38. static CoreExpression()
  39. {
  40. RegisterFunction("Format", (p, v) =>
  41. {
  42. if (!(p[0].Evaluate(v) is string format)) throw new Exception("No format string given for Format()");
  43. return string.Format(format, p.Skip(1).Select(x => x.Evaluate(v)).ToArray());
  44. });
  45. RegisterFunction("Client_LoadDocument", Fnc_LoadDocument);
  46. }
  47. private static object? Fnc_LoadDocument(IExpression[] p, IDictionary<string, object> v)
  48. {
  49. var id = p[0].Evaluate(v);
  50. if (id is null)
  51. return null;
  52. if (!(id is Guid docID))
  53. return null;
  54. return new Client<Document>()
  55. .Query(
  56. new Filter<Document>(x => x.ID).IsEqualTo(docID),
  57. new Columns<Document>(x => x.Data))
  58. .Rows.FirstOrDefault()
  59. ?.Get<Document, byte[]>(x => x.Data);
  60. }
  61. public static void RegisterFunction(string name, FncType function) =>
  62. _functions.Add(new Tuple<string, FncType>(name, function));
  63. #endregion
  64. }
  65. public class CoreExpression<TModel, TReturn> : CoreExpression
  66. where TModel : IExpressionModel<TReturn>
  67. {
  68. protected override Type? ReturnType => typeof(TReturn);
  69. public CoreExpression(string expressionString): base(expressionString) { }
  70. public new TReturn Evaluate(Dictionary<string, object?>? variables)
  71. {
  72. var result = base.Evaluate(variables);
  73. if(result is TReturn ret)
  74. {
  75. return ret;
  76. }
  77. return default(TReturn);
  78. }
  79. }
  80. }