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); } } }
// Helper to eval an arg that might be a lambda. internal DValue <T> EvalArg <T>(FormulaValue arg, SymbolContext context, IRContext irContext) where T : ValidFormulaValue { if (arg is LambdaFormulaValue lambda) { var val = lambda.Eval(this, context); return(val switch { T t => DValue <T> .Of(t), BlankValue b => DValue <T> .Of(b), ErrorValue e => DValue <T> .Of(e), _ => DValue <T> .Of(CommonErrors.RuntimeTypeMismatch(irContext)) });
public static Func <EvalVisitor, SymbolContext, IRContext, TableValue[], FormulaValue> StandardSingleColumnTable <T>(Func <EvalVisitor, SymbolContext, IRContext, T[], FormulaValue> targetFunction) where T : FormulaValue { return((runner, symbolContext, irContext, args) => { var tableType = (TableType)irContext.ResultType; var resultType = tableType.ToRecord(); var itemType = resultType.GetFieldType(BuiltinFunction.OneColumnTableResultNameStr); var arg0 = args[0]; var resultRows = new List <DValue <RecordValue> >(); foreach (var row in arg0.Rows) { if (row.IsValue) { var value = row.Value.GetField(BuiltinFunction.ColumnName_ValueStr); NamedValue namedValue; namedValue = value switch { T t => new NamedValue(BuiltinFunction.OneColumnTableResultNameStr, targetFunction(runner, symbolContext, IRContext.NotInSource(itemType), new T[] { t })), BlankValue bv => new NamedValue(BuiltinFunction.OneColumnTableResultNameStr, bv), ErrorValue ev => new NamedValue(BuiltinFunction.OneColumnTableResultNameStr, ev), _ => new NamedValue(BuiltinFunction.OneColumnTableResultNameStr, CommonErrors.RuntimeTypeMismatch(IRContext.NotInSource(itemType))) }; var record = new InMemoryRecordValue(IRContext.NotInSource(resultType), new List <NamedValue>() { namedValue }); resultRows.Add(DValue <RecordValue> .Of(record)); } else if (row.IsBlank) { resultRows.Add(DValue <RecordValue> .Of(row.Blank)); } else { resultRows.Add(DValue <RecordValue> .Of(row.Error)); } } return new InMemoryTableValue(irContext, resultRows); }); }