public virtual async Task <IBifoqlObject> Apply(QueryContext context, bool resolveDeferred = true) { if (context.QueryTarget is IBifoqlError) { return(context.QueryTarget); } if (context.QueryTarget is IBifoqlDeferredQueryInternal) { // A deferred query is a query that won't actually be evaluated here, but by some other // service. For example, let's say that I have another REST service that provides a BifoQL // endpoint. I can take this query and pass it along to that endpoint and get the result back. var deferred = ((IBifoqlDeferredQueryInternal)context.QueryTarget); var query = "@ | " + this.ToString(); var bifoqlObject = await deferred.EvaluateQuery(query); return(bifoqlObject.ToBifoqlObject()); } var result = await DoApply(context); if (resolveDeferred && result is IBifoqlDeferredQueryInternal) { result = await DeferredQueryWrapper.EvaluateDeferredQuery(result); } return(result); }
private async Task <IBifoqlObject> GetKeyFromObject(IBifoqlObject target, QueryContext context) { // Propagate errors. if (target is IBifoqlError) { return(target); } var lookup = target as IBifoqlLookupInternal; if (lookup != null) { Func <Task <IBifoqlObject> > value; if (lookup.TryGetValue(_key, out value)) { return(await value()); } else { return(new AsyncError(Location, $"key '{_key}' not found")); } } var array = target as IBifoqlArrayInternal; if (array != null) { var result = new List <Func <Task <IBifoqlObject> > >(); foreach (var item in array) { var resolvedItem = await item(); var entry = GetKeyFromObject(resolvedItem, context); result.Add(() => entry); } return(new AsyncArray(result)); } if (target is IBifoqlUndefined) { return(AsyncUndefined.Instance); } var deferred = target as IBifoqlDeferredQueryInternal; if (deferred != null) { return(DeferredQueryWrapper.AddToQuery(deferred, RightHandSideString())); } return(new AsyncError(this.Location, "key expression must be applied to array or map")); }
protected override async Task <IBifoqlObject> DoApply(QueryContext context) { var target = Target == null ? context.QueryTarget : await Target.Apply(context, resolveDeferred : false); target = await target.GetDefaultValueFromIndex(); // Propagate errors. if (target is IBifoqlError) { return(target); } var deferred = target as IBifoqlDeferredQueryInternal; if (deferred != null) { return(DeferredQueryWrapper.AddToQuery(deferred, RightHandSideString())); } var list = target as IBifoqlArrayInternal; if (list == null) { return(new AsyncError(this.Location, "Can only apply filter to an array")); } var result = new List <Func <Task <IBifoqlObject> > >(); var resolvedCondition = Condition.Simplify(context.Variables); foreach (var item in list) { var val = await item(); var condition = (await Condition.Apply(context.ReplaceTarget(val))) as IBifoqlBoolean; if (condition == null) { return(new AsyncError(this.Location, "Filter condition must evaluate to boolean")); } if (await condition.Value) { result.Add(item); } } return(new AsyncArray(result)); }
protected override async Task <IBifoqlObject> DoApply(QueryContext context) { var result = await First.Apply(context, resolveDeferred : false); result = await result.GetDefaultValue(); // Propagate errors. if (result is IBifoqlError) { return(result); } var deferred = result as IBifoqlDeferredQueryInternal; if (deferred != null) { return(DeferredQueryWrapper.AddToQuery(deferred, RightHandSideString())); } var array = result as IBifoqlArrayInternal; if (_chainBehavior == ChainBehavior.ToMultiple || (array != null && _chainBehavior == ChainBehavior.ToMultipleIfArray)) { if (array == null) { return(new AsyncError(this.Location, "pipe to multiple only works on an array")); } var resultList = new List <Func <Task <IBifoqlObject> > >(); foreach (var entry in array) { var entryValue = await entry(); var newContext = context.ReplaceTarget(entryValue); resultList.Add(() => Next.Apply(newContext)); } return(new AsyncArray(resultList)); } else { return(Next == null ? result : await Next.Apply(context.ReplaceTarget(result))); } }
protected override async Task <IBifoqlObject> DoApply(QueryContext context) { var target = Target == null ? context.QueryTarget : await Target.Apply(context, resolveDeferred : false); target = await target.GetDefaultValueFromIndex(); // Propagate errors if (target is IBifoqlError) { return(target); } var index = await _index.Apply(context); var lookup = target as IBifoqlMapInternal; if (lookup != null && index is IBifoqlString) { var key = await((IBifoqlString)index).Value; Func <Task <IBifoqlObject> > value; if (lookup.TryGetValue(key, out value)) { return(await value()); } else { return(AsyncUndefined.Instance); } } var array = target as IBifoqlArrayInternal; if (array != null && index is IBifoqlNumber) { var i = (int)await((IBifoqlNumber)index).Value; if (i < 0) { if (-i > array.Count) { return(AsyncUndefined.Instance); } return(await array[array.Count + i]()); } else { if (i >= array.Count) { return(AsyncUndefined.Instance); } return(await array[i]()); } } if (target is IBifoqlUndefined) { return(AsyncUndefined.Instance); } var deferred = target as IBifoqlDeferredQueryInternal; if (deferred != null) { return(DeferredQueryWrapper.AddToQuery(deferred, RightHandSideString())); } return(new AsyncError(this.Location, "key expression must be applied to array or map")); }