예제 #1
0
        private static FormulaValue RunAggregator(IAggregator agg, EvalVisitor runner, SymbolContext context, IRContext irContext, FormulaValue[] args)
        {
            var arg0 = (TableValue)args[0];
            var arg1 = (LambdaFormulaValue)args[1];

            foreach (DValue <RecordValue> row in arg0.Rows)
            {
                if (row.IsValue)
                {
                    var childContext = context.WithScopeValues(row.Value);
                    var value        = arg1.Eval(runner, childContext);

                    if (value is NumberValue number)
                    {
                        value = FiniteChecker(irContext, 0, number);
                    }

                    if (value is ErrorValue error)
                    {
                        return(error);
                    }
                    agg.Apply(value);
                }
            }

            return(agg.GetResult(irContext));
        }
예제 #2
0
        private static IEnumerable <DValue <RecordValue> > LazyAddColumns(EvalVisitor runner, SymbolContext context, IEnumerable <DValue <RecordValue> > sources, IRContext recordIRContext, NamedLambda[] newColumns)
        {
            foreach (var row in sources)
            {
                if (row.IsValue)
                {
                    // $$$ this is super inefficient... maybe a custom derived RecordValue?
                    var fields = new List <NamedValue>(row.Value.Fields);

                    var childContext = context.WithScopeValues(row.Value);

                    foreach (var column in newColumns)
                    {
                        var value = column.Lambda.Eval(runner, childContext);
                        fields.Add(new NamedValue(column.Name, value));
                    }

                    yield return(DValue <RecordValue> .Of(new InMemoryRecordValue(recordIRContext, fields.ToArray())));
                }
                else
                {
                    yield return(row);
                }
            }
        }
예제 #3
0
        private static IEnumerable <DValue <RecordValue> > LazyFilter(EvalVisitor runner,
                                                                      SymbolContext context,
                                                                      IEnumerable <DValue <RecordValue> > sources,
                                                                      LambdaFormulaValue filter)
        {
            foreach (var row in sources)
            {
                if (row.IsValue)
                {
                    var childContext = context.WithScopeValues(row.Value);

                    // Filter evals to a boolean
                    var  result  = filter.Eval(runner, childContext);
                    bool include = false;
                    if (result is BooleanValue booleanValue)
                    {
                        include = booleanValue.Value;
                    }

                    if (include)
                    {
                        yield return(row);
                    }
                }
            }
        }
예제 #4
0
        public static FormulaValue SortTable(EvalVisitor runner, SymbolContext symbolContext, IRContext irContext, FormulaValue[] args)
        {
            var arg0 = (TableValue)args[0];
            var arg1 = (LambdaFormulaValue)args[1];
            var arg2 = (StringValue)args[2];

            var pairs = arg0.Rows.Select(row =>
            {
                if (row.IsValue)
                {
                    var childContext = symbolContext.WithScopeValues(row.Value);
                    return(new KeyValuePair <DValue <RecordValue>, FormulaValue>(row, arg1.Eval(runner, childContext)));
                }
                return(new KeyValuePair <DValue <RecordValue>, FormulaValue>(row, row.ToFormulaValue()));
            }).ToList();

            var errors = new List <ErrorValue>(pairs.Select(pair => pair.Value).OfType <ErrorValue>());

            var allNumbers  = pairs.All(pair => IsValueTypeErrorOrBlank <NumberValue>(pair.Value));
            var allStrings  = pairs.All(pair => IsValueTypeErrorOrBlank <StringValue>(pair.Value));
            var allBooleans = pairs.All(pair => IsValueTypeErrorOrBlank <BooleanValue>(pair.Value));

            if (!(allNumbers || allStrings || allBooleans))
            {
                errors.Add(CommonErrors.RuntimeTypeMismatch(irContext));
                return(ErrorValue.Combine(irContext, errors));
            }

            if (errors.Count != 0)
            {
                return(ErrorValue.Combine(irContext, errors));
            }

            var compareToResultModifier = 1;

            if (arg2.Value.ToLower() == "descending")
            {
                compareToResultModifier = -1;
            }

            if (allNumbers)
            {
                return(SortValueType <NumberValue, double>(pairs, irContext, compareToResultModifier));
            }
            else if (allStrings)
            {
                return(SortValueType <StringValue, string>(pairs, irContext, compareToResultModifier));
            }
            else
            {
                return(SortValueType <BooleanValue, bool>(pairs, irContext, compareToResultModifier));
            }
        }
예제 #5
0
        public static FormulaValue CountIf(EvalVisitor runner, SymbolContext symbolContext, IRContext irContext, FormulaValue[] args)
        {
            // Streaming
            var sources = (TableValue)args[0];
            var filter  = (LambdaFormulaValue)args[1];

            int count = 0;

            var errors = new List <ErrorValue>();

            foreach (var row in sources.Rows)
            {
                if (row.IsValue)
                {
                    var childContext = symbolContext.WithScopeValues(row.Value);
                    var result       = filter.Eval(runner, childContext);

                    if (result is ErrorValue error)
                    {
                        errors.Add(error);
                        continue;
                    }

                    bool include = ((BooleanValue)result).Value;

                    if (include)
                    {
                        count++;
                    }
                }
                if (row.IsError)
                {
                    errors.Add(row.Error);
                }
            }

            if (errors.Count != 0)
            {
                return(ErrorValue.Combine(irContext, errors));
            }

            return(new NumberValue(irContext, count));
        }
예제 #6
0
        public static FormulaValue Concat(EvalVisitor runner, SymbolContext symbolContext, IRContext irContext, FormulaValue[] args)
        {// Streaming
            var arg0 = (TableValue)args[0];
            var arg1 = (LambdaFormulaValue)args[1];

            StringBuilder sb = new StringBuilder();

            foreach (var row in arg0.Rows)
            {
                if (row.IsValue)
                {
                    var childContext = symbolContext.WithScopeValues(row.Value);

                    // Filter evals to a boolean
                    var result = arg1.Eval(runner, childContext);

                    var str = (StringValue)result;
                    sb.Append(str.Value);
                }
            }

            return(new StringValue(irContext, sb.ToString()));
        }