public bool any(ScriptScopeContext scope, object target) => target.AssertEnumerable(nameof(any)).Any();
public bool all(ScriptScopeContext scope, object target, object expression) => all(scope, target, expression, null);
public override Task WriteAsync(ScriptScopeContext scope, PageBlockFragment block, CancellationToken token) { var invokerCtx = (Tuple <string, StaticMethodInvoker>)scope.Context.CacheMemory.GetOrAdd(block.Argument, key => { var literal = block.Argument.Span.ParseVarName(out var name); var strName = name.ToString(); literal = literal.AdvancePastWhitespace(); literal = literal.AdvancePastWhitespace(); var args = TypeConstants.EmptyStringList; if (!literal.IsEmpty) { literal = literal.ParseArgumentsList(out var argIdentifiers); args = argIdentifiers.Map(x => x.Name); } var strFragment = (PageStringFragment)block.Body[0]; var script = ScriptPreprocessors.TransformStatementBody(strFragment.ValueString); var parsedScript = scope.Context.OneTimePage(script); StaticMethodInvoker invoker = null; // Allow recursion by initializing lazy Delegate object LazyInvoker(object instance, object[] paramValues) { if (invoker == null) { throw new NotSupportedException($"Uninitialized function '{strName}'"); } return(invoker(instance, paramValues)); } invoker = (paramValues) => { scope.PageResult.StackDepth++; try { var pageResult = new PageResult(parsedScript) { Args = { [strName] = (MethodInvoker)LazyInvoker }, StackDepth = scope.PageResult.StackDepth }; var len = Math.Min(paramValues.Length, args.Count); for (int i = 0; i < len; i++) { var paramValue = paramValues[i]; pageResult.Args[args[i]] = paramValue; } var discard = ScriptContextUtils.GetPageResultOutput(pageResult); if (pageResult.ReturnValue == null) { throw new NotSupportedException(ScriptContextUtils.ErrorNoReturn); } return(pageResult.ReturnValue.Result); } finally { scope.PageResult.StackDepth--; } }; return(Tuple.Create(strName, invoker)); }); scope.PageResult.Args[invokerCtx.Item1] = invokerCtx.Item2; return(TypeConstants.EmptyTask); }
public object sum(ScriptScopeContext scope, object target, object expression, object scopeOptions) => applyInternal(nameof(sum), scope, target, expression, scopeOptions, (a, b) => a + b);
public IEnumerable <object> thenByDescending(ScriptScopeContext scope, object target, object expression, object scopeOptions) => thenByInternal(nameof(thenByDescending), scope, target, expression, scopeOptions);
public int count(ScriptScopeContext scope, object target) => target.AssertEnumerable(nameof(count)).Count();
public double average(ScriptScopeContext scope, object target, object expression, object scopeOptions) => applyInternal(nameof(average), scope, target, expression, scopeOptions, (a, b) => a + b).ConvertTo <double>() / target.AssertEnumerable(nameof(average)).Count();
public IEnumerable <object> orderByDesc(ScriptScopeContext scope, object target, object expression) => orderByDesc(scope, target, expression, null);
public double average(ScriptScopeContext scope, object target) => average(scope, target, null, null);
public double average(ScriptScopeContext scope, object target, object expression) => average(scope, target, expression, null);
public object max(ScriptScopeContext scope, object target, object expression, object scopeOptions) => applyInternal(nameof(max), scope, target, expression, scopeOptions, (a, b) => b > a ? b : a);
public object max(ScriptScopeContext scope, object target, object expression) => max(scope, target, expression, null);
public object max(ScriptScopeContext scope, object target) => max(scope, target, null, null);
public IEnumerable <object> skipWhile(ScriptScopeContext scope, object target, object expression) => skipWhile(scope, target, expression, null);
private object applyInternal(string filterName, ScriptScopeContext scope, object target, object expression, object scopeOptions, Func <double, double, double> fn) { if (target is double d) { return(fn(d, expression.ConvertTo <double>())); } if (target is int i) { return((int)fn(i, expression.ConvertTo <double>())); } if (target is long l) { return((long)fn(l, expression.ConvertTo <double>())); } var items = target.AssertEnumerable(filterName); var total = filterName == nameof(min) ? double.MaxValue : 0; Type itemType = null; if (expression != null) { var expr = scope.AssertExpression(filterName, expression, scopeOptions, out var itemBinding); foreach (var item in items) { if (item == null) { continue; } scope.AddItemToScope(itemBinding, item); var result = expr.Evaluate(scope); if (result == null) { continue; } if (itemType == null) { itemType = result.GetType(); } total = fn(total, result.ConvertTo <double>()); } } else { foreach (var item in items) { if (item == null) { continue; } if (itemType == null) { itemType = item.GetType(); } total = fn(total, item.ConvertTo <double>()); } } if (filterName == nameof(min) && itemType == null) { return(0); } if (expression == null && itemType == null) { itemType = target.GetType().FirstGenericType()?.GetGenericArguments().FirstOrDefault(); } return(itemType == null || itemType == typeof(double) ? total : total.ConvertTo(itemType)); }
public IEnumerable <object> orderBy(ScriptScopeContext scope, object target, object expression, object scopeOptions) => orderByInternal(nameof(orderBy), scope, target, expression, scopeOptions);
public object reduce(ScriptScopeContext scope, object target, object expression) => reduce(scope, target, expression, null);
public IEnumerable <object> thenByDescending(ScriptScopeContext scope, object target, object expression) => thenByDescending(scope, target, expression, null);
public object let(ScriptScopeContext scope, object target, object scopeBindings) //from filter { if (target is IEnumerable objs) { string itemBinding; Dictionary <string, object> scopedParams = null; var arrowExpr = scopeBindings as JsArrowFunctionExpression; if (arrowExpr != null) { itemBinding = arrowExpr.Params[0].Name; } else { scopedParams = scope.GetParamsWithItemBindingOnly(nameof(@let), null, scopeBindings, out itemBinding); } var to = new List <ScopeVars>(); var i = 0; foreach (var item in objs) { scope.ScopedParams[ScriptConstants.Index] = i++; scope.ScopedParams[itemBinding] = item; // Copy over previous let bindings into new let bindings var itemBindings = new ScopeVars(); if (item is object[] tuple) { foreach (var a in tuple) { if (a is IDictionary <string, object> aArgs) { foreach (var entry in aArgs) { itemBindings[entry.Key] = entry.Value; } } } } if (arrowExpr != null) { var value = arrowExpr.Body.Evaluate(scope); if (value is Dictionary <string, object> bindingVars) { foreach (var bindingVar in bindingVars) { itemBindings[bindingVar.Key] = bindingVar.Value; } } } else { foreach (var entry in scopedParams) { var bindTo = entry.Key; if (!(entry.Value is string bindToLiteral)) { throw new NotSupportedException($"'{nameof(let)}' in '{scope.Page.VirtualPath}' expects a string Expression for its value but received '{entry.Value}' instead"); } bindToLiteral.ParseJsExpression(out JsToken token); try { var bindValue = token.Evaluate(scope); scope.ScopedParams[bindTo] = bindValue; itemBindings[bindTo] = bindValue; } catch (Exception exception) { Console.WriteLine(exception); } } } to.Add(itemBindings); } return(to); } if (target != null) { throw new NotSupportedException($"'{nameof(let)}' in '{scope.Page.VirtualPath}' requires an IEnumerable but received a '{target.GetType()?.Name}' instead"); } return(null); }
public IEnumerable <object> skip(ScriptScopeContext scope, IEnumerable <object> original, object countOrBinding) => original.Skip(scope.GetValueOrEvaluateBinding <int>(countOrBinding));
public object first(ScriptScopeContext scope, object target, object expression) => first(scope, target, expression, null);
public int count(ScriptScopeContext scope, object target, object expression) => count(scope, target, expression, null);
public object last(ScriptScopeContext scope, object target) => target.AssertEnumerable(nameof(last)).LastOrDefault();
public override Task WriteAsync(ScriptScopeContext scope, PageBlockFragment block, CancellationToken token) => TypeConstants.EmptyTask;
public object sum(ScriptScopeContext scope, object target) => sum(scope, target, null, null);