Exemplo n.º 1
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            object result = null;
            string error;

            object instance;

            (instance, error) = expression.Children[0].TryEvaluate(state, options);
            if (error == null)
            {
                var   isInstanceList = false;
                IList list           = null;
                if (FunctionUtils.TryParseList(instance, out IList ilist))
                {
                    isInstanceList = true;
                    list           = ilist;
                }
                else if (instance is JObject jobj)
                {
                    list = FunctionUtils.Object2KVPairList(jobj);
                }
                else if (FunctionUtils.ConvertToJToken(instance) is JObject jobject)
                {
                    list = FunctionUtils.Object2KVPairList(jobject);
                }
                else
                {
                    error = $"{expression.Children[0]} is not a collection or structure object to run foreach";
                }

                if (error == null)
                {
                    var iteratorName  = (string)(expression.Children[1].Children[0] as Constant).Value;
                    var stackedMemory = StackedMemory.Wrap(state);
                    result = new List <object>();
                    for (var idx = 0; idx < list.Count; idx++)
                    {
                        var local = new Dictionary <string, object>
                        {
                            { iteratorName, FunctionUtils.AccessIndex(list, idx).value },
                        };

                        // the local iterator is pushed as one memory layer in the memory stack
                        stackedMemory.Push(new SimpleObjectMemory(local));
                        var(r, e) = expression.Children[2].TryEvaluate(stackedMemory, new Options(options)
                        {
                            NullSubstitution = null
                        });
                        stackedMemory.Pop();

                        if (FunctionUtils.IsLogicTrue(r) && e == null)
                        {
                            // add if only if it evaluates to true
                            ((List <object>)result).Add(local[iteratorName]);
                        }
                    }

                    if (!isInstanceList)
                    {
                        // re-construct object
                        var jobjResult = new JObject();
                        foreach (var item in (List <object>)result)
                        {
                            FunctionUtils.TryAccessProperty(item, "key", out var keyVal);
                            FunctionUtils.TryAccessProperty(item, "value", out var val);
                            jobjResult.Add(keyVal as string, FunctionUtils.ConvertToJToken(val));
                        }

                        result = jobjResult;
                    }
                }
            }

            return(result, error);
        }