Ejemplo n.º 1
0
        public object reduce(ScriptScopeContext scope, object target, object expression, object scopeOptions)
        {
            var  items    = target.AssertEnumerable(nameof(reduce));
            Type itemType = null;

            if (!(expression is JsArrowFunctionExpression arrowExpr))
            {
                throw new NotSupportedException($"{nameof(reduce)} expects an arrow expression but was instead '{expression.GetType().Name}'");
            }

            if (arrowExpr.Params.Length != 2)
            {
                throw new NotSupportedException($"{nameof(reduce)} expects 2 params but was instead {arrowExpr.Params.Length}");
            }

            var accumulatorBinding = arrowExpr.Params[0].Name;
            var itemBinding        = arrowExpr.Params[1].Name;
            var expr = arrowExpr.Body;

            var scopedParams = scopeOptions as Dictionary <string, object> ?? new Dictionary <string, object>();

            var accumulator = scopedParams.TryGetValue("initialValue", out object initialValue)
                ? initialValue.ConvertTo <double>()
                : !(scopeOptions is IDictionary)
                    ? scopeOptions.ConvertTo <double>()
                    : 0;

            var i = 0;

            scope = scope.Clone();
            foreach (var item in items)
            {
                if (item == null)
                {
                    continue;
                }

                scope.AddItemToScope(accumulatorBinding, accumulator);
                scope.AddItemToScope("index", i++);
                scope.AddItemToScope(itemBinding, item);

                var result = expr.Evaluate(scope);
                if (result == null)
                {
                    continue;
                }
                if (itemType == null)
                {
                    itemType = result.GetType();
                }

                accumulator = result.ConvertTo <double>();
            }

            return(itemType == null || itemType == typeof(double)
                ? accumulator
                : accumulator.ConvertTo(itemType));
        }
Ejemplo n.º 2
0
        public IgnoreResult forEach(ScriptScopeContext scope, object target, JsArrowFunctionExpression arrowExpr)
        {
            var token = arrowExpr.Body;

            scope = scope.Clone();
            if (target is IList list)
            {
                var itemBinding  = arrowExpr.Params[0].Name;
                var indexBinding = arrowExpr.Params.Length > 1 ? arrowExpr.Params[1].Name : ScriptConstants.Index;
                var arrayBinding = arrowExpr.Params.Length > 2 ? arrowExpr.Params[2].Name : null;

                for (var i = 0; i < list.Count; i++)
                {
                    scope.ScopedParams[indexBinding] = i;
                    if (arrayBinding != null)
                    {
                        scope.ScopedParams[arrayBinding] = list;
                    }

                    scope = scope.AddItemToScope(itemBinding, list[i]);
                    token.Evaluate(scope);
                }
            }
            else if (target is IDictionary d)
            {
                if (arrowExpr.Params.Length != 2)
                {
                    throw new NotSupportedException("Dictionary.forEach requires 2 lambda params");
                }

                var keyBinding   = arrowExpr.Params[0].Name;
                var valueBinding = arrowExpr.Params[1].Name;

                foreach (var key in d.Keys)
                {
                    scope.ScopedParams[keyBinding]   = key;
                    scope.ScopedParams[valueBinding] = d[key];
                    token.Evaluate(scope);
                }
            }
            else
            {
                throw new NotSupportedException("Can only use forEach on Lists or Dictionaries");
            }

            return(IgnoreResult.Value);
        }
Ejemplo n.º 3
0
        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)
            {
                scope = scope.Clone();
                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));
        }