コード例 #1
0
        private static EvaluationResult GroupBy(Context context, ArrayLiteral receiver, EvaluationResult arg, EvaluationStackFrame captures)
        {
            var closure = Converter.ExpectClosure(arg);

            using (var disposableFrame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
            {
                // To avoid warning: access to disposable closure.
                var frame = disposableFrame;
                var entry = context.TopStack;

                var result = receiver.Values.GroupBy(obj =>
                {
                    frame.SetArgument(0, obj);
                    return(context.InvokeClosure(closure, frame));
                });

                var arr = result.Select(grp =>
                {
                    var grpArrayLit = ArrayLiteral.CreateWithoutCopy(grp.ToArray(), entry.InvocationLocation, entry.Path);
                    var bindings    = new List <Binding>
                    {
                        new Binding(StringId.Create(context.FrontEndContext.StringTable, "key"), grp.Key, location: default(LineInfo)),
                        new Binding(StringId.Create(context.FrontEndContext.StringTable, "values"), grpArrayLit, location: default(LineInfo)),
                    };
                    return(EvaluationResult.Create(ObjectLiteral.Create(bindings, entry.InvocationLocation, entry.Path)));
                }).ToArray();

                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(arr, entry.InvocationLocation, entry.Path)));
            }
        }
コード例 #2
0
        private static EvaluationResult Reduce(Context context, ArrayLiteral receiver, EvaluationResult arg0, EvaluationResult arg1, EvaluationStackFrame captures)
        {
            var closure     = Converter.ExpectClosure(arg0);
            int paramsCount = closure.Function.Params;

            var accumulator = arg1;

            if (receiver.Length > 0)
            {
                using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
                {
                    for (int i = 0; i < receiver.Length; i++)
                    {
                        frame.TrySetArguments(paramsCount, accumulator, receiver[i], i, EvaluationResult.Create(receiver));
                        accumulator = context.InvokeClosure(closure, frame);
                        if (accumulator.IsErrorValue)
                        {
                            return(EvaluationResult.Error);
                        }
                    }
                }
            }

            return(accumulator);
        }
コード例 #3
0
        private static EvaluationResult Map(Context context, ArrayLiteral receiver, EvaluationResult arg, EvaluationStackFrame captures)
        {
            var closure = Converter.ExpectClosure(arg);

            int paramsCount = closure.Function.Params;

            if (receiver.Length == 0)
            {
                return(EvaluationResult.Create(receiver));
            }

            var result = new EvaluationResult[receiver.Length];

            using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
            {
                for (int i = 0; i < receiver.Length; ++i)
                {
                    frame.TrySetArguments(paramsCount, receiver[i], i, EvaluationResult.Create(receiver));
                    result[i] = context.InvokeClosure(closure, frame);

                    if (result[i].IsErrorValue)
                    {
                        return(EvaluationResult.Error);
                    }
                }

                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(result, context.TopStack.InvocationLocation, context.TopStack.Path)));
            }
        }
コード例 #4
0
ファイル: AmbientArray.cs プロジェクト: rustedwizard/BuildXL
        private static EvaluationResult Find(Context context, ArrayLiteral receiver, EvaluationResult arg, EvaluationStackFrame captures)
        {
            var closure = Converter.ExpectClosure(arg);

            int paramsCount = closure.Function.Params;

            using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
            {
                for (int i = 0; i < receiver.Length; ++i)
                {
                    frame.TrySetArguments(paramsCount, receiver[i], i, EvaluationResult.Create(receiver));
                    EvaluationResult lambdaResult = context.InvokeClosure(closure, frame);

                    if (lambdaResult.IsErrorValue)
                    {
                        return(EvaluationResult.Error);
                    }

                    if (Expression.IsTruthy(lambdaResult))
                    {
                        return(receiver[i]);
                    }
                }

                return(EvaluationResult.Undefined);
            }
        }
コード例 #5
0
ファイル: AmbientSet.cs プロジェクト: socat/BuildXL
        private static EvaluationResult ForEach(Context context, OrderedSet receiver, EvaluationResult arg, EvaluationStackFrame captures)
        {
            var cls         = Converter.ExpectClosure(arg);
            var result      = new EvaluationResult[receiver.Count];
            int paramsCount = cls.Function.Params;

            using (var frame = EvaluationStackFrame.Create(cls.Function, captures.Frame))
            {
                int i = 0;

                foreach (var item in receiver)
                {
                    frame.TrySetArguments(paramsCount, item);
                    result[i] = context.InvokeClosure(cls, frame);

                    if (result[i].IsErrorValue)
                    {
                        return(EvaluationResult.Error);
                    }

                    ++i;
                }

                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(result, context.TopStack.InvocationLocation, context.TopStack.Path)));
            }
        }
コード例 #6
0
ファイル: AmbientMap.cs プロジェクト: kittinap/kunnjae
        private static EvaluationResult ForEach(Context context, OrderedMap receiver, EvaluationResult arg, EvaluationStackFrame captures)
        {
            var cls         = Converter.ExpectClosure(arg);
            var result      = new EvaluationResult[receiver.Count];
            int paramsCount = cls.Function.Params;

            // One frame can be reused for multiple calls of a callback function
            using (var frame = EvaluationStackFrame.Create(cls.Function, captures.Frame))
            {
                var entry = context.TopStack;

                int i = 0;

                foreach (var kvp in receiver)
                {
                    var kvpAsArray = ArrayLiteral.CreateWithoutCopy(new EvaluationResult[] { kvp.Key, kvp.Value }, entry.InvocationLocation, entry.Path);

                    frame.TrySetArguments(paramsCount, EvaluationResult.Create(kvpAsArray));
                    result[i] = context.InvokeClosure(cls, frame);

                    if (result[i].IsErrorValue)
                    {
                        return(EvaluationResult.Error);
                    }

                    ++i;
                }

                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(result, entry.InvocationLocation, entry.Path)));
            }
        }
コード例 #7
0
        private static EvaluationResult MapMany(Context context, ArrayLiteral receiver, EvaluationResult arg, EvaluationStackFrame captures)
        {
            var closure     = Converter.ExpectClosure(arg);
            int paramsCount = closure.Function.Params;

            if (receiver.Length == 0)
            {
                return(EvaluationResult.Create(receiver));
            }

            // WIP: try to pool this
            var arrays = new ArrayLiteral[receiver.Length];
            int count  = 0;

            using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
            {
                for (int i = 0; i < receiver.Length; ++i)
                {
                    frame.TrySetArguments(paramsCount, receiver[i], i, EvaluationResult.Create(receiver));
                    EvaluationResult mapResult = context.InvokeClosure(closure, frame);

                    if (mapResult.IsErrorValue)
                    {
                        return(EvaluationResult.Error);
                    }

                    if (!(mapResult.Value is ArrayLiteral mappedElems))
                    {
                        throw Converter.CreateException <ArrayLiteral>(mapResult, default(ConversionContext));
                    }

                    arrays[i] = mappedElems;
                    count    += mappedElems.Length;
                }

                if (count == 0)
                {
                    return(EvaluationResult.Create(arrays[0]));
                }

                var result    = new EvaluationResult[count];
                var nextIndex = 0;

                for (int i = 0; i < arrays.Length; ++i)
                {
                    var array  = arrays[i];
                    var length = array.Length;

                    if (length > 0)
                    {
                        array.Copy(0, result, nextIndex, length);
                    }

                    nextIndex += length;
                }

                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(result, context.TopStack.InvocationLocation, context.TopStack.Path)));
            }
        }
コード例 #8
0
ファイル: ObjectLiteral.cs プロジェクト: kittinap/kunnjae
        /// <summary>
        /// Helper method that returns a (object, object) -> object from a closure
        /// </summary>
        protected static MergeFunction GetCustomMergeFunctionFromClosure(Context context, EvaluationStackFrame captures, EvaluationResult customMergeClosure)
        {
            var closure     = Converter.ExpectClosure(customMergeClosure);
            int paramsCount = closure.Function.Params;

            return((leftObject, rightObject) =>
            {
                using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
                {
                    frame.TrySetArguments(paramsCount, leftObject, rightObject);
                    return context.InvokeClosure(closure, frame);
                }
            });
        }
コード例 #9
0
        private EvaluationResult ExpectFailure(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var closure         = Args.AsClosure(args, 0);
            var expectedResults = Args.AsArrayLiteral(args, 1);

            using (var frame = EvaluationStackFrame.Create(closure.Function, args.Frame))
            {
                var result = context.InvokeClosure(closure, frame);
                if (!result.IsErrorValue)
                {
                    Assert.True(false, "Expected the code under test to throw a failure, but none was returned.");
                }

                if (!m_getDiagnostics().Any(diagnostic => diagnostic.Level == EventLevel.Error))
                {
                    Assert.True(false, "Expected to see at least one reported error, but none encountered.");
                }

                for (int i = 0; i < expectedResults.Count; i++)
                {
                    if (expectedResults[i].Value is string expectedContent)
                    {
                        // String case
                        Assert.False(string.IsNullOrEmpty(expectedContent), "Empty strings are not supported as expected error messages");
                        ValidateExpectedMessageLogged(null, expectedContent);
                    }
                    else
                    {
                        // Object case
                        var obj = Converter.ExpectObjectLiteral(
                            expectedResults[i],
                            new ConversionContext(pos: i, objectCtx: expectedResults));

                        var code = Converter.ExtractInt(obj, m_testingExpectedMessageCode);
                        expectedContent = Converter.ExtractString(obj, m_testingExpectedMessageContent);

                        ValidateExpectedMessageLogged(code, expectedContent);
                    }
                }

                return(EvaluationResult.Undefined);
            }
        }
コード例 #10
0
        private static EvaluationResult MapWithState(Context context, ArrayLiteral receiver, EvaluationResult arg0, EvaluationResult arg1, EvaluationStackFrame captures)
        {
            var closure     = Converter.ExpectClosure(arg0);
            int paramsCount = closure.Function.Params;
            var state       = arg1;
            var arrays      = new EvaluationResult[receiver.Length];

            using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
            {
                var entry = context.TopStack;

                var stateName = SymbolAtom.Create(context.FrontEndContext.StringTable, "state");
                var elemsName = SymbolAtom.Create(context.FrontEndContext.StringTable, "elems");
                var elemName  = SymbolAtom.Create(context.FrontEndContext.StringTable, "elem");

                for (int i = 0; i < receiver.Length; ++i)
                {
                    frame.TrySetArguments(paramsCount, state, receiver[i], i, EvaluationResult.Create(receiver));
                    EvaluationResult mapResult = context.InvokeClosure(closure, frame);

                    if (mapResult.IsErrorValue)
                    {
                        return(EvaluationResult.Error);
                    }

                    if (!(mapResult.Value is ObjectLiteral objectResult))
                    {
                        throw Converter.CreateException <ObjectLiteral>(mapResult, default(ConversionContext));
                    }

                    arrays[i] = objectResult[elemName];
                    state     = objectResult[stateName];
                }

                var bindings = new List <Binding>
                {
                    new Binding(elemsName, ArrayLiteral.CreateWithoutCopy(arrays, entry.InvocationLocation, entry.Path), location: default(LineInfo)),
                    new Binding(stateName, state, location: default(LineInfo)),
                };
                return(EvaluationResult.Create(ObjectLiteral.Create(bindings, entry.InvocationLocation, entry.Path)));
            }
        }
コード例 #11
0
        private static EvaluationResult SomeOrAll(Context context, ArrayLiteral receiver, EvaluationResult arg, EvaluationStackFrame captures, bool isSome)
        {
            var closure = Converter.ExpectClosure(arg);

            if (receiver.Length == 0)
            {
                return(EvaluationResult.Create(!isSome));
            }

            int paramsCount = closure.Function.Params;

            using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
            {
                for (int i = 0; i < receiver.Length; ++i)
                {
                    frame.TrySetArguments(paramsCount, receiver[i], i, EvaluationResult.Create(receiver));
                    EvaluationResult lambdaResult = context.InvokeClosure(closure, frame);

                    if (lambdaResult.IsErrorValue)
                    {
                        return(EvaluationResult.Error);
                    }

                    bool isTrue = Expression.IsTruthy(lambdaResult);
                    if (isSome && isTrue)
                    {
                        return(EvaluationResult.True);
                    }

                    if (!isSome && !isTrue)
                    {
                        return(EvaluationResult.False);
                    }
                }

                // if isSome ("some") and we've exhausted the loop (no elem matched) ==> return false
                // if !isSome ("all") and we've exhausted the loop (all elems matched) ==> return true
                return(EvaluationResult.Create(!isSome));
            }
        }
コード例 #12
0
        private static EvaluationResult MapDefined(Context context, ArrayLiteral receiver, EvaluationResult arg, EvaluationStackFrame captures)
        {
            var closure     = Converter.ExpectClosure(arg);
            int paramsCount = closure.Function.Params;

            if (receiver.Length == 0)
            {
                return(EvaluationResult.Create(receiver));
            }

            var result = new EvaluationResult[receiver.Length];

            using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
            {
                int j = 0;
                for (int i = 0; i < receiver.Length; ++i)
                {
                    frame.TrySetArguments(paramsCount, receiver[i], i, EvaluationResult.Create(receiver));
                    EvaluationResult r = context.InvokeClosure(closure, frame);

                    if (r.IsErrorValue)
                    {
                        return(EvaluationResult.Error);
                    }

                    // Skip the result if undefined.
                    if (!r.IsUndefined)
                    {
                        result[j] = r;
                        ++j;
                    }
                }

                var definedResult = new EvaluationResult[j];
                Array.Copy(result, 0, definedResult, 0, j);
                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(definedResult, context.TopStack.InvocationLocation, context.TopStack.Path)));
            }
        }
コード例 #13
0
        private static EvaluationResult ZipWith(Context context, ArrayLiteral receiver, EvaluationResult arg0, EvaluationResult arg1, EvaluationStackFrame captures)
        {
            var arrayToZipWith = Converter.ExpectArrayLiteral(arg0);
            var closure        = Converter.ExpectClosure(arg1);
            int paramsCount    = closure.Function.Params;

            if (receiver.Length == 0)
            {
                return(EvaluationResult.Create(receiver));
            }

            if (arrayToZipWith.Length == 0)
            {
                return(EvaluationResult.Create(arrayToZipWith));
            }

            // The returned array has the size of the smallest array
            var result = new EvaluationResult[Math.Min(receiver.Length, arrayToZipWith.Length)];

            using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
            {
                for (int i = 0; i < result.Length; ++i)
                {
                    // zipWith callback takes 2 arguments: from the receiver and from the first argument of a zipWith function.
                    frame.TrySetArguments(paramsCount, receiver[i], arrayToZipWith[i]);
                    result[i] = context.InvokeClosure(closure, frame);

                    if (result[i].IsErrorValue)
                    {
                        return(EvaluationResult.Error);
                    }
                }

                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(result, context.TopStack.InvocationLocation, context.TopStack.Path)));
            }
        }
コード例 #14
0
        private static EvaluationResult Sort(Context context, ArrayLiteral receiver, EvaluationResult arg, EvaluationStackFrame captures)
        {
            if (receiver.Length <= 1)
            {
                return(EvaluationResult.Create(receiver));
            }

            bool hasErrors = false;
            var  closure   = Converter.ExpectClosure(arg, new ConversionContext(allowUndefined: true, pos: 1));

            IEnumerable <EvaluationResult> sortedArray;

            if (closure == null)
            {
                EvaluationResult firstElem  = receiver.Values.First();
                object           firstValue = firstElem.Value;
                if (firstValue is int)
                {
                    sortedArray = receiver.Values.OrderBy(e => Converter.ExpectNumber(e, context: new ConversionContext(objectCtx: e)), Comparer <int> .Default);
                }
                else if (firstValue is string)
                {
                    sortedArray = receiver.Values.OrderBy(e => Converter.ExpectString(e, context: new ConversionContext(objectCtx: e)), Comparer <string> .Default);
                }
                else
                {
                    throw Converter.CreateException(
                              expectedTypes: new[] { typeof(int), typeof(string) },
                              value: firstElem,
                              context: new ConversionContext(pos: 1, objectCtx: receiver));
                }
            }
            else
            {
                using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
                {
                    sortedArray = receiver.Values.OrderBy(e => e, Comparer <EvaluationResult> .Create((lhs, rhs) =>
                    {
                        if (lhs.IsErrorValue || rhs.IsErrorValue)
                        {
                            hasErrors = true;
                            return(0);
                        }

                        frame.SetArgument(0, lhs);
                        frame.SetArgument(1, rhs);
                        EvaluationResult compareResult = context.InvokeClosure(closure, frame);
                        if (compareResult.IsErrorValue)
                        {
                            hasErrors = true;
                            return(0);
                        }

                        return(Converter.ExpectNumber(compareResult, context: new ConversionContext(objectCtx: closure)));
                    }));
                }
            }

            var entry = context.TopStack;
            var sortedArrayMaterialized = sortedArray.ToArray();
            var result = hasErrors
                ? (object)ErrorValue.Instance
                : ArrayLiteral.CreateWithoutCopy(sortedArrayMaterialized, entry.InvocationLocation, entry.Path);

            return(EvaluationResult.Create(result));
        }
コード例 #15
0
        private static EvaluationResult Filter(Context context, ArrayLiteral receiver, EvaluationResult arg, EvaluationStackFrame captures)
        {
            var closure = Converter.ExpectClosure(arg);

            if (receiver.Length == 0)
            {
                return(EvaluationResult.Create(receiver));
            }

            // [a,b,c].filter(x => x !== undefined) is a common pattern.
            // Using a specialized filtering logic improves performance.
            bool isSpecialUndefinedCheck = IsSpecialUndefinedCheck(closure);

            // The following variable contains a list of indices that changed the predicate value from true to false and vice versa.
            // Consider following example:
            // [1,2,3,4,5].filter(x => x > 3);
            // In this case we'll get the following values in indices variable:
            // [0, // starting index: assume that predicate is true at the beginning
            // 0, // the first element yields 'false'
            // 3, // 3-d index yield 'true'
            // 5] // will contains the size of the array if the predicate yielded 'true' at the end of the loop.
            // To filter the array using this table, we just need to copy all
            // elements in every range: 'even index' to 'even index + 1' because those ranges contains
            // indices when predicate yielded 'true'.

            // This approach saves both memory and improve perf (0.5Gb for Analog repo and even more for OneCore).
            // Instead of allocating another array this function will allocate the list that will be
            // twice as small in the worst case (when every element yields different result).
            List <int> indices = new List <int>()
            {
                0
            };

            bool lastPredicate   = true;
            int  resultingLength = 0;
            int  paramsCount     = closure.Function.Params;

            // Allocating the frame.

            // Needed only for non-optimized version. If the predicate is just a null check, no frames were needed.
            using (var frame = isSpecialUndefinedCheck ? default(EvaluationStackFrame) : EvaluationStackFrame.Create(closure.Function, captures.Frame))
            {
                int i;
                for (i = 0; i < receiver.Length; ++i)
                {
                    EvaluationResult valueToCompare = receiver[i];

                    // In a better world, the following logic would be extracted in the separate method.
                    // But in the current one it will require a method with 7-8 arguments.
                    // So, keeping the logic right in the loop.
                    bool predicateResult;
                    if (isSpecialUndefinedCheck)
                    {
                        predicateResult = !valueToCompare.IsUndefined;
                    }
                    else
                    {
                        frame.TrySetArguments(paramsCount, receiver[i], i, EvaluationResult.Create(receiver));
                        valueToCompare = context.InvokeClosure(closure, frame);

                        if (valueToCompare.IsErrorValue)
                        {
                            return(EvaluationResult.Error);
                        }

                        predicateResult = Expression.IsTruthy(valueToCompare);
                    }

                    if (predicateResult != lastPredicate)
                    {
                        lastPredicate = predicateResult;
                        indices.Add(i);
                    }

                    if (predicateResult)
                    {
                        resultingLength++;
                    }
                }

                if (lastPredicate)
                {
                    indices.Add(i);
                }

                if (resultingLength == receiver.Length)
                {
                    // Nothing was filtered.
                    // Just returning the same result.
                    return(EvaluationResult.Create(receiver));
                }

                EvaluationResult[] result = resultingLength == 0 ? CollectionUtilities.EmptyArray <EvaluationResult>() : new EvaluationResult[resultingLength];

                // Now we need to copy all the items from the source array
                int targetIndex = 0;
                for (int idx = 0; idx < indices.Count; idx += 2)
                {
                    int sourceIndex = indices[idx];
                    int length      = indices[idx + 1] - sourceIndex;
                    receiver.Copy(sourceIndex, result, targetIndex, length);
                    targetIndex += length;
                }

                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(result, context.TopStack.InvocationLocation, context.TopStack.Path)));
            }
        }