示例#1
0
        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);
        }
示例#2
0
        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"));
        }
示例#3
0
        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));
        }
示例#4
0
        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)));
            }
        }
示例#5
0
        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"));
        }