public static IEnumerable <SearchItem> Apply(SearchExpressionContext c) { if (c.args.Length == 0) { c.ThrowError("Invalid Arguments"); } var resultStreamExpr = c.args[0]; if (!resultStreamExpr.types.IsIterable()) { c.ThrowError($"No iterators", resultStreamExpr.outerText); } var exprs = new List <SearchExpression>(c.expression.parameters.Length); for (var i = 1; i < c.expression.parameters.Length; ++i) { var templateExpr = c.expression.parameters[i]; var currentStreamName = $"apply@stream#{i}"; var currentStream = SearchExpression.CreateStreamExpression(resultStreamExpr, currentStreamName); var args = new[] { currentStream }.Concat(templateExpr.parameters).ToArray(); var innerText = templateExpr.innerText; var evaluator = templateExpr.evaluator; if (templateExpr.types.HasFlag(SearchExpressionType.Function)) { // Back patch arguments var restOfArguments = templateExpr.innerText.Substring(templateExpr.evaluator.name.Length + 1); innerText = $"{templateExpr.evaluator.name}{{{currentStreamName}, {restOfArguments}}}".GetStringView(); } else if (templateExpr.types.HasFlag(SearchExpressionType.Text)) { // String literal used as an evaluator name: var filterFunction = EvaluatorManager.GetEvaluatorByNameDuringEvaluation(templateExpr.innerText.ToString(), templateExpr.innerText, c); innerText = $"{templateExpr.innerText}{{{currentStreamName}}}".GetStringView(); evaluator = filterFunction; } else { c.ThrowError($"Bad argument type", templateExpr.outerText); } var patchedExpr = new SearchExpression(templateExpr.types, templateExpr.outerText, innerText, evaluator, args); exprs.Add(patchedExpr); resultStreamExpr = patchedExpr; } // Pull on the last element to start the evaluation chain return(exprs.Last().Execute(c)); }