public static IEnumerable <SearchItem> Sum(SearchExpressionContext c) { var skipCount = 0; string selector = null; if (c.args[0].types.HasFlag(SearchExpressionType.Selector)) { skipCount++; selector = c.args[0].innerText.ToString(); } return(c.ForEachArgument(skipCount).AggregateResults(0d, (context, item, sum) => Aggregate(item, selector, sum, (d, _sum) => _sum + d), (context, sum) => EvaluatorUtils.CreateItem(sum, context.ResolveAlias("Sum")))); }
public static IEnumerable <SearchItem> Min(SearchExpressionContext c) { var skipCount = 0; string selector = null; if (c.args[0].types.HasFlag(SearchExpressionType.Selector)) { skipCount++; selector = c.args[0].innerText.ToString(); } return(c.ForEachArgument(skipCount).AggregateResults(double.MaxValue, (context, item, min) => Aggregate(item, selector, min, (d, _min) => d < _min), (context, min) => EvaluatorUtils.CreateItem(min, context.ResolveAlias("Min")))); }
public static bool Check(SearchExpression e, SearchExpressionContext c) { var result = e.Execute(c); var count = result.Count(); if (count == 0) { return(false); } if (count == 1) { return(IsTrue(result.First())); } return(true); }
public static IEnumerable <SearchItem> Sort(SearchExpressionContext c) { var dataSet = c.args[0]; bool sortAscend = true; if (c.args.Length == 3) { var sortAscendExpr = c.args[2]; if (sortAscendExpr.IsKeyword(SearchExpressionKeyword.Desc)) { sortAscend = false; } else { sortAscend = sortAscendExpr.GetBooleanValue(sortAscend); } } var sortComparer = new SortItemComparer(c.args[1].innerText.ToString(), sortAscend); var sortedSet = new List <SearchItem>(); var selectExpression = dataSet.Apply(nameof(Select), c.args[1]); foreach (var r in selectExpression.Execute(c)) { if (r != null) { var insertAt = sortedSet.BinarySearch(r, sortComparer); if (insertAt < 0) { insertAt = ~insertAt; } sortedSet.Insert(insertAt, r); } else { yield return(null); } } int score = 0; foreach (var r in sortedSet) { r.score = score++; yield return(r); } }
public static IEnumerable <SearchItem> Range(SearchExpressionContext c) { var range = new RangeDouble(); var alias = c.ResolveAlias("Range"); foreach (var sr in c.args[0].Execute(c)) { if (GetRange(sr, ref range)) { break; } else { yield return(null); } } if (!range.valid) { if (c.args.Length < 2) { c.ThrowError("No expression to end range"); } foreach (var sr in c.args[1].Execute(c)) { if (GetRange(sr, ref range)) { break; } else { yield return(null); } } } if (!range.valid) { c.ThrowError("Incomplete range"); } for (double d = range.start.Value; d < range.end.Value; d += 1d) { yield return(EvaluatorUtils.CreateItem(d, alias)); } }
public static void ValidateExpressionArguments(SearchExpressionContext c, IEnumerable <Signature> signatures) { // First pass to get all valid argument number signatures (must do a ToList to separate the 2 passes) // Second pass to validate the argument types. The last error is kept (lowest number of arguments if no signature matches the number of argument, wrong type if there is at least one) var lastError = ""; var errorPosition = StringView.Null; if (signatures.Where(s => ValidateExpressionArgumentsCount(c.expression.evaluator.name, c.args, s, (msg, errorPos) => { lastError = msg; errorPosition = errorPos; })).ToList() .Any(s => ValidateExpressionArguments(c.expression.evaluator.name, c.args, s, (msg, errorPos) => { lastError = msg; errorPosition = errorPos; }))) { return; } if (!errorPosition.valid) { errorPosition = c.expression.innerText; } c.ThrowError($"Error while evaluating arguments for {c.expression.evaluator.name}. {lastError}", errorPosition); }
public static IEnumerable <SearchItem> If(SearchExpressionContext c) { if (c.args.Length < 2) { c.ThrowError("Not enough parameters for if"); } bool cond = false; foreach (var item in c.args[0].Execute(c)) { if (item == null) { yield return(null); } else { cond |= EvaluatorUtils.IsTrue(item); if (!cond) { break; } } } if (cond) { foreach (var item in c.args[1].Execute(c)) { yield return(item); } } else if (c.args.Length == 2) { // Nothing to do. } else { foreach (var item in c.args[2].Execute(c)) { yield return(item); } } }
public static IEnumerable <SearchItem> Evaluate(SearchExpressionContext c, SearchExpression expression) { var concurrentList = new ConcurrentBag <SearchItem>(); var yieldSignal = new EventWaitHandle(false, EventResetMode.AutoReset); var task = Task.Run(() => { var enumerable = expression.Execute(c, SearchExpressionExecutionFlags.ThreadedEvaluation); foreach (var searchItem in enumerable) { if (searchItem != null) { concurrentList.Add(searchItem); yieldSignal.Set(); } } }); while (!concurrentList.IsEmpty || !TaskHelper.IsTaskFinished(task)) { if (!yieldSignal.WaitOne(0)) { if (concurrentList.IsEmpty) { Dispatcher.ProcessOne(); } yield return(null); } while (concurrentList.TryTake(out var item)) { yield return(item); } } if (task.IsFaulted && task.Exception?.InnerException != null) { if (task.Exception.InnerException is SearchExpressionEvaluatorException sex) { throw sex; } UnityEngine.Debug.LogException(task.Exception.InnerException); } }
public static IEnumerable <SearchItem> GroupBy(SearchExpressionContext c) { string selector = null; if (c.args.Length > 1) { selector = c.args[1].innerText.ToString(); } var outputValueFieldName = System.Guid.NewGuid().ToString("N"); var dataSet = SelectorManager.SelectValues(c.search, c.args[0].Execute(c), selector, outputValueFieldName); foreach (var _group in dataSet.GroupBy(item => item.GetValue(outputValueFieldName))) { var group = _group; var groupId = group.Key?.ToString() ?? $"group{++s_NextGroupId}"; if (c.HasFlag(SearchExpressionExecutionFlags.Expand)) { var evaluator = new SearchExpressionEvaluator(groupId, _ => group, SearchExpressionEvaluationHints.Default); var genExpr = new SearchExpression(SearchExpressionType.Group, groupId.GetStringView(), groupId.GetStringView(), (group.Key?.ToString() ?? groupId).GetStringView(), evaluator); yield return(EvaluatorUtils.CreateSearchExpressionItem(genExpr)); } else { SearchProvider groupProvider = null; foreach (var item in group) { if (groupProvider == null) { groupProvider = SearchUtils.CreateGroupProvider(item.provider, groupId, s_NextGroupId); } item.provider = groupProvider; yield return(item); } } } }
public static IEnumerable <SearchItem> Select(SearchExpressionContext c) { if (c.args.Length < 2) { c.ThrowError($"Invalid arguments"); } // Select dataset var dataset = c.args[0].Execute(c); const int batchSize = 100; foreach (var batch in dataset.Batch(batchSize)) { var results = batch; var sIt = c.args.Skip(1).GetEnumerator(); while (sIt.MoveNext()) { var selector = sIt.Current; if (IsSelectorLiteral(selector)) { var selectorName = selector.innerText.ToString(); var selectorAlias = c.ResolveAlias(selector); results = TaskEvaluatorManager.EvaluateMainThread(results, item => { var selectedValue = SelectorManager.SelectValue(item, c.search, selectorName, out string suggestedSelectorName); AddSelectedValue(item, selector.innerText.ToString(), selectorAlias ?? suggestedSelectorName, selectedValue); return(item); }, batchSize); } else { results = ProcessIterableSelector(c, results, selector); } } foreach (var r in results) { yield return(r); } } }
public static IEnumerable <SearchItem> Sum(SearchExpressionContext c) { var skipCount = 0; string selector = null; if (c.args[0].types.HasFlag(SearchExpressionType.Selector)) { skipCount++; selector = c.args[0].innerText.ToString(); } foreach (var arg in c.args.Skip(skipCount)) { var sum = 0d; foreach (var r in arg.Execute(c)) { sum = Aggregate(r, selector, sum, (d, _sum) => _sum + d); } yield return(SearchExpression.CreateItem(sum, c.ResolveAlias(arg, "Sum"))); } }
public static IEnumerable <SearchItem> Max(SearchExpressionContext c) { var skipCount = 0; string selector = null; if (c.args[0].types.HasFlag(SearchExpressionType.Selector)) { skipCount++; selector = c.args[0].innerText.ToString(); } foreach (var arg in c.args.Skip(skipCount)) { double max = double.MinValue; foreach (var r in arg.Execute(c)) { max = Aggregate(r, selector, max, (d, _max) => d > _max); } yield return(SearchExpression.CreateItem(max, c.ResolveAlias(arg, "Max"))); } }
public static IEnumerable <SearchItem> Avg(SearchExpressionContext c) { var skipCount = 0; string selector = null; if (c.args[0].types.HasFlag(SearchExpressionType.Selector)) { skipCount++; selector = c.args[0].innerText.ToString(); } foreach (var arg in c.args.Skip(skipCount)) { var avg = Average.Zero; foreach (var r in arg.Execute(c)) { avg = Aggregate(r, selector, avg, (d, _avg) => _avg.Add(d)); } yield return(SearchExpression.CreateItem(avg.result, c.ResolveAlias(arg, "Average"))); } }
public static IEnumerable <SearchItem> Random(SearchExpressionContext c) { if (c.args.Length == 0) { c.ThrowError("No arguments"); } foreach (var e in c.args) { if (e != null) { foreach (var r in Random(c, e)) { yield return(r); } } else { yield return(null); } } }
static IEnumerable <SearchItem> Random(SearchExpressionContext c, SearchExpression e) { var set = new List <SearchItem>(); foreach (var item in e.Execute(c)) { if (item != null) { set.Add(item); } yield return(null); // Wait until we have all results. } var randomItem = Random(set); // Rename random item label if an alias is defined. if (c.ResolveAlias(e) is string alias) { randomItem.label = alias; } yield return(randomItem); }
public static IEnumerable <SearchItem> Map(SearchExpressionContext c) { var mapSet = c.args[0].Execute(c); var mapQuery = c.args[1]; foreach (var m in mapSet) { if (m == null) { yield return(null); } else { using (c.runtime.Push(m)) { foreach (var e in mapQuery.Execute(c)) { yield return(e); } } } } }
public static IEnumerable <SearchItem> IsTrue(SearchExpressionContext c) { foreach (var e in c.args) { bool isTrue = false; foreach (var item in e.Execute(c)) { if (item == null) { yield return(null); } else { isTrue |= EvaluatorUtils.IsTrue(item); if (!isTrue) { break; } } } yield return(EvaluatorUtils.CreateItem(isTrue, c.ResolveAlias(e, "IsTrue"))); } }
internal IEnumerable <SearchItem> Execute(SearchExpressionContext c, SearchExpressionExecutionFlags executionFlags) { if (!evaluator.valid || evaluator.execute == null) { c.ThrowError("Invalid expression evaluator"); } try { if (!evaluator.hints.HasFlag(SearchExpressionEvaluationHints.ThreadNotSupported)) { return(Evaluate(c, executionFlags)); } // We cannot only return the IEnumerable of the evaluator, as the iteration itself needs to be // done on the main thread. If we return the IEnumerable itself, we will unroll the items and call the evaluator // in the evaluation thread. return(TaskEvaluatorManager.EvaluateMainThreadUnroll(() => Evaluate(c, executionFlags))); } catch (SearchExpressionEvaluatorException ex) { ExceptionDispatchInfo.Capture(ex).Throw(); return(null); // To stop visual studio complaining about not all code path return a value } }
public static IEnumerable <SearchItem> Union(SearchExpressionContext c) { if (c.args == null || c.args.Length == 0) { c.ThrowError("Nothing to merge"); } var set = new HashSet <int>(); foreach (var e in c.args) { foreach (var item in e.Execute(c)) { if (item == null) { yield return(null); } else if (set.Add(item.value.GetHashCode())) { yield return(item); } } } }
public static IEnumerable <SearchItem> Selection(SearchExpressionContext c) { var selection = TaskEvaluatorManager.EvaluateMainThread(() => { var instanceIds = UnityEditor.Selection.instanceIDs; return(instanceIds.Select(id => { string assetPath = AssetDatabase.GetAssetPath(id); return new SelectionResult(id, assetPath); }).ToList()); }); foreach (var selectionResult in selection) { if (string.IsNullOrEmpty(selectionResult.assetPath)) { yield return(SearchExpression.CreateItem(selectionResult.instanceId, c.ResolveAlias("Selection"))); } else { yield return(SearchExpression.CreateItem(selectionResult.assetPath, c.ResolveAlias("Selection"))); } } }
public static IEnumerable <SearchItem> Constant(SearchExpressionContext c) { if (c.expression.types.HasAny(SearchExpressionType.Function)) { using (c.runtime.Push(c.args[0], c.args.Skip(1))) yield return(Constant(c.runtime.current).First()); } else if (c.expression.types.HasAny(SearchExpressionType.Number)) { yield return(SearchExpression.CreateItem(c.expression.GetNumberValue(), c.expression.alias.ToString())); } else if (c.expression.types.HasAny(SearchExpressionType.Text | SearchExpressionType.Keyword)) { yield return(SearchExpression.CreateItem(c.expression.innerText.ToString(), c.expression.alias.ToString())); } else if (c.expression.types.HasAny(SearchExpressionType.Boolean)) { yield return(SearchExpression.CreateItem(c.expression.GetBooleanValue(), c.expression.alias.ToString())); } else { c.ThrowError($"Invalid constant expression"); } }
ArgumentEnumerable(SearchExpressionContext c) { context = c; }
public static IEnumerable <SearchItem> Set(SearchExpressionContext c) { return(c.args.SelectMany(e => e.Execute(c))); }
public override IEnumerator <SearchItem> GetEnumerator() { foreach (var argument in m_ArgumentEnumerable) { var results = argument.Execute(context); if (results == null) { yield break; } bool started = false; SearchExpressionContext argContext = default; foreach (var searchItem in results) { if (m_SkipNullResult && searchItem == null) { yield return(null); continue; } if (!started) { // We need to start yielding result in order for the evaluation context to be valid. if (!context.valid) { context.ThrowError("Invalid argument context"); } argContext = context.runtime.current; OnAggregateStart(argContext); started = true; } OnAggregateResult(argContext, searchItem); yield return(null); } if (m_OnAggregateToSearchItem != null) { yield return(m_OnAggregateToSearchItem(argContext, m_Aggregator)); continue; } if (m_OnAggregateToSearchItems != null) { foreach (var searchItem in m_OnAggregateToSearchItems(argContext, m_Aggregator)) { yield return(searchItem); } continue; } if (m_Aggregator is IEnumerable <SearchItem> searchItemAggregator) { foreach (var searchItem in searchItemAggregator) { yield return(searchItem); } } } }
protected override void OnAggregateStart(SearchExpressionContext currentContext) { m_OnAggregateStart?.Invoke(currentContext, m_Aggregator); }
public static IEnumerable <SearchItem> ToBoolean(SearchExpressionContext c) { return(c.args.SelectMany(e => e.Execute(c)).Select(item => SearchExpression.CreateItem(SearchExpression.IsTrue(item)))); }
public static IEnumerable <SearchItem> SceneName(SearchExpressionContext c) { var desc = TaskEvaluatorManager.EvaluateMainThread(() => EditorApplication.GetApplicationTitleDescriptor()); yield return(SearchExpression.CreateItem(desc.activeSceneName ?? string.Empty, c.ResolveAlias("SceneName"))); }
public static IEnumerable <SearchItem> DataPath(SearchExpressionContext c) { var dataPath = TaskEvaluatorManager.EvaluateMainThread(() => Application.dataPath); yield return(SearchExpression.CreateItem(dataPath ?? string.Empty, c.ResolveAlias("DataPath"))); }
static void DefaultArgumentIteration(SearchExpressionContext c, SearchExpression e) { }
protected override void OnAggregateResult(SearchExpressionContext currentContext, SearchItem currentItem) { m_Aggregator = m_OnAggregateResult(currentContext, currentItem, m_Aggregator); }