Пример #1
0
        /// <summary>
        /// DScript exposes a value cache. The backing store is kept inside of 'IEvaluationScheduler'.
        /// Values from this cache should never be returned directly; instead, the result should be cloned first
        /// (to avoid exposing an observable side effect).
        /// </summary>
        private EvaluationResult GetOrAdd(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            Args.CheckArgumentIndex(args, 0);
            var key     = args[0];
            var closure = Args.AsClosure(args, 1);

            return(DoGetOrAdd(context, env, key, null, closure));
        }
Пример #2
0
        private EvaluationResult GetOrAdd(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            Args.CheckArgumentIndex(args, 0);
            var key     = args[0];
            var closure = Args.AsClosure(args, 1);

            var helper = new HashingHelper(context.PathTable, recordFingerprintString: false);

            // Add the qualifier to the key
            var qualifierId            = context.LastActiveModuleQualifier.QualifierId;
            var qualifierDisplayString = context.ContextTree.FrontEndContext.QualifierTable.GetQualifier(qualifierId).ToDisplayString(StringTable);

            helper.Add(qualifierDisplayString);
            if (!TryHashValue(key, helper))
            {
                return(EvaluationResult.Error);
            }

            var keyFingerprint = helper.GenerateHash();

            var resultToClone = context.ContextTree.ValueCache.GetOrAdd(
                keyFingerprint,
                _ =>
            {
                int paramsCount = closure.Function.Params;
                var newValue    = context.InvokeClosure(closure, closure.Frame);
                if (newValue.IsErrorValue)
                {
                    return(EvaluationResult.Error);
                }

                return(newValue);
            }
                );

            // The object returned will always be a cloned copy.
            // DScript is a side effect free language, but we use object identity
            // for equality comparison so to avoid making cache hits observable to
            // users we opt to clone the value from the cache each time, even after the
            // first time we add it to the cache.
            // This is also the reason why we don't have separate functions for inspecting or simply adding
            // because the results would be observable and potentially invalidating all the
            // incremental evaluations in DScript.
            return(DeepCloneValue(resultToClone));
        }
Пример #3
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);
            }
        }
Пример #4
0
        private EvaluationResult AddIfLazy(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var condition = Args.AsBool(args, 0);

            if (!condition)
            {
                // Return empty Array
                var entry = context.TopStack;
                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(new EvaluationResult[0], entry.InvocationLocation, entry.Path)));
            }

            // Call the function passed in and return that result
            var closure = Args.AsClosure(args, 1);
            var result  = context.InvokeClosure(closure, closure.Frame);

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

            return(result);
        }