Example #1
0
        /// <summary>
        /// Evaluates an R expresion in the specified environment, and returns an object describing the result.
        /// </summary>
        /// <param name="environmentExpression">
        /// R expression designating the environment in which <paramref name="expression"/> will be evaluated.
        /// </param>
        /// <param name="expression">Expression to evaluate.</param>
        /// <param name="name"><see cref="IREvaluationResultInfo.Name"/> of the returned evaluation result.</param>
        /// <param name="properties">Specifies which <see cref="IREvaluationResultInfo"/> properties should be present in the result.</param>
        /// <param name="repr">
        /// An R expression that must evaluate to a function that takes an R value as its sole argument, and returns the
        /// string representation of that argument as a single-element character vector. The representation is stored in
        /// <see cref="IRValueInfo.Representation"/> property of the produced result. If this argument is
        /// <see langword="null"/>, no representation is computed, and <see cref="IRValueInfo.Representation"/>
        /// will also be <see langword="null"/>.
        /// Use helper properties and methods in <see cref="RValueRepresentations"/> to obtain an appropriate expression
        /// for standard R functions such as <c>deparse()</c> or <c>str()</c>.
        /// </param>
        /// <remarks>
        /// <returns>
        /// If evaluation succeeded, an instance of <see cref="IRValueInfo"/> describing the resulting value.
        /// If evaluation failed with an error, an instance of <see cref="IRErrorInfo"/> describing the error.
        /// This method never returns <see cref="IRActiveBindingInfo"/> or <see cref="IRPromiseInfo"/>.
        /// </returns>
        public static async Task <IREvaluationResultInfo> TryEvaluateAndDescribeAsync(
            this IRExpressionEvaluator session,
            string environmentExpression,
            string expression,
            string name,
            REvaluationResultProperties properties,
            string repr,
            CancellationToken cancellationToken = default(CancellationToken)
            )
        {
            if (environmentExpression == null)
            {
                throw new ArgumentNullException(nameof(environmentExpression));
            }
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            await TaskUtilities.SwitchToBackgroundThread();

            environmentExpression = environmentExpression ?? "NULL";
            var code   = Invariant($"rtvs:::eval_and_describe({expression.ToRStringLiteral()}, ({environmentExpression}),, {properties.ToRVector()},, {repr})");
            var result = await session.EvaluateAsync <JObject>(code, REvaluationKind.Normal, cancellationToken);

            return(REvaluationResultInfo.Parse(session, environmentExpression, name, result));
        }
Example #2
0
        protected virtual async Task <IReadOnlyList <IRSessionDataObject> > GetChildrenAsyncInternal()
        {
            List <IRSessionDataObject> result = null;

            var valueEvaluation = DebugEvaluation as IRValueInfo;

            if (valueEvaluation == null)
            {
                Debug.Assert(false, $"{nameof(RSessionDataObject)} result type is not {nameof(IRValueInfo)}");
                return(result);
            }

            if (valueEvaluation.HasChildren)
            {
                await TaskUtilities.SwitchToBackgroundThread();

                const REvaluationResultProperties properties =
                    ExpressionProperty |
                    AccessorKindProperty |
                    TypeNameProperty |
                    ClassesProperty |
                    LengthProperty |
                    SlotCountProperty |
                    AttributeCountProperty |
                    DimProperty |
                    FlagsProperty;
                var children = await valueEvaluation.DescribeChildrenAsync(properties, RValueRepresentations.Str(MaxReprLength), MaxChildrenCount);

                result = EvaluateChildren(children);
            }

            return(result);
        }
Example #3
0
        protected virtual async Task <IReadOnlyList <IRSessionDataObject> > GetChildrenAsyncInternal()
        {
            var valueEvaluation = DebugEvaluation as IRValueInfo;

            if (valueEvaluation == null)
            {
                // Failed to fetch children - for example, because the object is already gone.
                return(null);
            }

            await TaskUtilities.SwitchToBackgroundThread();

            try {
                if (valueEvaluation.HasChildren)
                {
                    REvaluationResultProperties properties =
                        ExpressionProperty |
                        AccessorKindProperty |
                        TypeNameProperty |
                        ClassesProperty |
                        LengthProperty |
                        SlotCountProperty |
                        AttributeCountProperty |
                        DimProperty |
                        FlagsProperty |
                        (RToolsSettings.Current.EvaluateActiveBindings ? ComputedValueProperty : 0);
                    var children = await valueEvaluation.DescribeChildrenAsync(properties, RValueRepresentations.Str(MaxReprLength), MaxChildrenCount);

                    return(EvaluateChildren(children));
                }
            } catch (REvaluationException) { }

            return(null);
        }
Example #4
0
 /// <summary>
 /// Like <see cref="TryEvaluateAndDescribeAsync(IRSession, string, REvaluationResultProperties, string, CancellationToken)"/>,
 /// but throws <see cref="RException"/> if result is an <see cref="IRErrorInfo"/>.
 /// </summary>
 public static Task<IRValueInfo> EvaluateAndDescribeAsync(
     this IRSession session,
     string expression,
     REvaluationResultProperties properties,
     string repr,
     CancellationToken cancellationToken = default(CancellationToken)
 ) =>
     session.EvaluateAndDescribeAsync(REnvironments.GlobalEnv, expression, null, properties, repr, cancellationToken);
Example #5
0
 /// <summary>
 /// Like <see cref="RSessionExtensions.DescribeChildrenAsync"/>, but returns children of the object described
 /// by the provided evaluation info.
 /// </summary>
 public static Task <IReadOnlyList <IREvaluationResultInfo> > DescribeChildrenAsync(
     this IREvaluationResultInfo info,
     REvaluationResultProperties properties,
     string repr,
     int?maxCount = null,
     CancellationToken cancellationToken = default(CancellationToken)
     ) =>
 info.Evaluator.DescribeChildrenAsync(info.EnvironmentExpression, info.Expression, properties, repr, maxCount, cancellationToken);
Example #6
0
 /// <summary>
 /// Like <see cref="RSessionExtensions.DescribeChildrenAsync"/>, but returns children of the object described
 /// by the provided evaluation info.
 /// </summary>
 public static Task<IReadOnlyList<IREvaluationResultInfo>> DescribeChildrenAsync(
     this IREvaluationResultInfo info,
     REvaluationResultProperties properties,
     string repr,
     int? maxCount = null,
     CancellationToken cancellationToken = default(CancellationToken)
 ) =>
     info.Session.DescribeChildrenAsync(info.EnvironmentExpression, info.Expression, properties, repr, maxCount, cancellationToken);
Example #7
0
 /// <summary>
 /// Like <see cref="RSessionExtensions.DescribeChildrenAsync"/>, but returns children of this environment.
 /// </summary>
 /// <remarks>
 /// If this method is called on a stale frame (i.e if call stack has changed since the <see cref="RSessionExtensions.TracebackAsync"/>
 /// call that produced this frame), the result is undefined - the method can throw <see cref="RException"/>, or produce meaningless
 /// output.
 /// </remarks>
 public static Task <IReadOnlyList <IREvaluationResultInfo> > DescribeChildrenAsync(
     this IRStackFrame frame,
     REvaluationResultProperties properties,
     string repr,
     int?maxCount = null,
     CancellationToken cancellationToken = default(CancellationToken)
     ) =>
 frame.Session.DescribeChildrenAsync(frame.EnvironmentExpression, "base::environment()", properties, repr, maxCount, cancellationToken);
Example #8
0
 /// <summary>
 /// Like <see cref="TryEvaluateAndDescribeAsync(IRSession, string, REvaluationResultProperties, string, CancellationToken)"/>,
 /// but throws <see cref="RException"/> if result is an <see cref="IRErrorInfo"/>.
 /// </summary>
 public static Task <IRValueInfo> EvaluateAndDescribeAsync(
     this IRExpressionEvaluator session,
     string expression,
     REvaluationResultProperties properties,
     string repr,
     CancellationToken cancellationToken = default(CancellationToken)
     ) =>
 session.EvaluateAndDescribeAsync(REnvironments.GlobalEnv, expression, null, properties, repr, cancellationToken);
Example #9
0
 /// <summary>
 /// Same as <see cref="EvaluateAndDescribeAsync(IRStackFrame, string, string, REvaluationResultProperties, string, CancellationToken)"/>,
 /// but uses <see langword="null"/> for <c>name</c>.
 /// </summary>
 public static Task <IRValueInfo> EvaluateAndDescribeAsync(
     this IRStackFrame frame,
     string expression,
     REvaluationResultProperties properties,
     string repr,
     CancellationToken cancellationToken = default(CancellationToken)
     ) =>
 frame.EvaluateAndDescribeAsync(expression, null, properties, repr, cancellationToken);
Example #10
0
        private async Task <IRValueInfo> EvaluateAndDescribeAsync(REnvironment env)
        {
            await TaskUtilities.SwitchToBackgroundThread();

            const REvaluationResultProperties properties = ClassesProperty | ExpressionProperty | TypeNameProperty | DimProperty | LengthProperty;

            return(await _session.EvaluateAndDescribeAsync(env.EnvironmentExpression, properties, null));
        }
Example #11
0
 /// <summary>
 /// Produces an object describing this frame's environment. <see cref="REvaluationResultInfoExtensions.DescribeChildrenAsync"/>
 /// method can then be used to retrieve the variables in the frame.
 /// </summary>
 /// <param name="properties">
 /// Which properties of the returned object should be provided. Note that it should include at least the following flags
 /// argument value in order for <see cref="REvaluationResultInfoExtensions.DescribeChildrenAsync"/> to be working.
 /// </param>
 /// <remarks>
 /// <para>
 /// There is no guarantee that the returned evaluation result is <see cref="IRValueInfo"/>. Retrieving the frame environment involves
 /// evaluating <see cref="EnvironmentExpression"/>, and like any evaluation, it can fail. Caller should check for <see cref="IRErrorInfo"/>
 /// and handle it accordingly. However, it is never <see cref="IRPromiseInfo"/> or <see cref="IRActiveBindingInfo"/>.
 /// </para>
 /// <para>
 /// If this method is called on a stale frame (i.e if call stack has changed since the <see cref="RSessionExtensions.TracebackAsync"/>
 /// call that produced this frame), the result is undefined, and can be an error result, or contain unrelated data.
 /// </para>
 /// </remarks>
 public static Task <IRValueInfo> DescribeEnvironmentAsync(
     this IRStackFrame frame,
     REvaluationResultProperties properties,
     CancellationToken cancellationToken = default(CancellationToken)
     )
 {
     properties |= ExpressionProperty | LengthProperty | AttributeCountProperty | FlagsProperty;
     return(frame.EvaluateAndDescribeAsync("base::environment()", properties, null, cancellationToken));
 }
Example #12
0
 /// <summary>
 /// Same as <see cref="Microsoft.R.DataInspection.RSessionExtensions.TryEvaluateAndDescribeAsync(string, string, string, REvaluationResultProperties, int?, CancellationToken)"/>,
 /// but passes <see cref="EnvironmentExpression"/> of this frame as <c>environmentExpression</c> argument,
 /// </summary>
 public static Task <IREvaluationResultInfo> TryEvaluateAndDescribeAsync(
     this IRStackFrame frame,
     string expression,
     string name,
     REvaluationResultProperties properties,
     string repr,
     CancellationToken cancellationToken = default(CancellationToken)
     ) =>
 frame.Session.TryEvaluateAndDescribeAsync(frame.EnvironmentExpression, expression, name, properties, repr, cancellationToken);
Example #13
0
        protected async Task<IRValueInfo> EvaluateAsync(string expression, REvaluationResultProperties fields, string repr, CancellationToken cancellationToken) {
            var result = await Evaluator.EvaluateAsync(expression, fields, repr, cancellationToken);
            var error = result as IRErrorInfo;
            if (error != null) {
                await VsAppShell.Current.SwitchToMainThreadAsync(cancellationToken);
                VsAppShell.Current.ShowErrorMessage(error.ErrorText);
                return null;
            }

            return result as IRValueInfo;
        }
Example #14
0
        protected async Task <IRValueInfo> EvaluateAsync(string expression, REvaluationResultProperties fields, string repr, CancellationToken cancellationToken)
        {
            var result = await Evaluator.EvaluateAsync(expression, fields, repr, cancellationToken);

            if (result is IRErrorInfo error)
            {
                await Services.MainThread().SwitchToAsync(cancellationToken);

                Services.UI().ShowErrorMessage(error.ErrorText);
                return(null);
            }
            return(result as IRValueInfo);
        }
Example #15
0
        private async Task UpdateList()
        {
            if (_updating)
            {
                return;
            }

            try {
                _updating = true;
                // May be null in tests
                var sessionProvider = EditorShell.Current.ExportProvider.GetExportedValueOrDefault <IRSessionProvider>();
                var session         = sessionProvider.GetOrCreate(GuidList.InteractiveWindowRSessionGuid);
                if (session.IsHostRunning)
                {
                    var stackFrames = await session.TracebackAsync();

                    var globalStackFrame = stackFrames.FirstOrDefault(s => s.IsGlobal);
                    if (globalStackFrame != null)
                    {
                        const REvaluationResultProperties properties =
                            ExpressionProperty |
                            AccessorKindProperty |
                            TypeNameProperty |
                            ClassesProperty |
                            LengthProperty |
                            SlotCountProperty |
                            AttributeCountProperty |
                            DimProperty |
                            FlagsProperty;
                        var evaluation = await globalStackFrame.TryEvaluateAndDescribeAsync("base::environment()", "Global Environment", properties, RValueRepresentations.Str());

                        var e = new RSessionDataObject(evaluation);  // root level doesn't truncate children and return every variables

                        _topLevelVariables.Clear();

                        var children = await e.GetChildrenAsync();

                        if (children != null)
                        {
                            foreach (var x in children)
                            {
                                _topLevelVariables[x.Name] = x; // TODO: BUGBUG: this doesn't address removed variables
                            }
                        }
                    }
                }
            } finally {
                _updating = false;
            }
        }
Example #16
0
        private async Task UpdateList()
        {
            if (_updating)
            {
                return;
            }

            try {
                _updating = true;
                // May be null in tests
                if (Session.IsHostRunning)
                {
                    var stackFrames = await Session.TracebackAsync();

                    var globalStackFrame = stackFrames.FirstOrDefault(s => s.IsGlobal);
                    if (globalStackFrame != null)
                    {
                        const REvaluationResultProperties properties =
                            ExpressionProperty |
                            AccessorKindProperty |
                            TypeNameProperty |
                            ClassesProperty |
                            LengthProperty |
                            SlotCountProperty |
                            AttributeCountProperty |
                            DimProperty |
                            FlagsProperty;
                        var evaluation = await globalStackFrame.TryEvaluateAndDescribeAsync("base::environment()", "Global Environment", properties, RValueRepresentations.Str());

                        var settings = _services.GetService <IRSettings>();
                        var e        = new RSessionDataObject(evaluation, settings.EvaluateActiveBindings); // root level doesn't truncate children and return every variables

                        _topLevelVariables.Clear();

                        var children = await e.GetChildrenAsync();

                        if (children != null)
                        {
                            foreach (var x in children)
                            {
                                _topLevelVariables[x.Name] = x; // TODO: BUGBUG: this doesn't address removed variables
                            }
                        }
                    }
                }
            } catch (REvaluationException) { } finally {
                _updating = false;
            }
        }
Example #17
0
        public async Task<IREvaluationResultInfo> EvaluateAsync(string expression, REvaluationResultProperties fields, string repr, CancellationToken cancellationToken = default(CancellationToken)) {
            await TaskUtilities.SwitchToBackgroundThread();

            repr = repr ?? RValueRepresentations.Str();

            // Don't cache sessions since they can be disposed, expecially the debug session
            // when host is restarts or gets re-created in tests
            var rSession = _workflow.RSession;

            var frames = await rSession.TracebackAsync(cancellationToken:cancellationToken);
            if (frames == null || frames.Count == 0) {
                throw new InvalidOperationException("Debugger frames stack is empty");
            }
            return await frames.Last().TryEvaluateAndDescribeAsync(expression, fields, repr, cancellationToken) as IRValueInfo;
        }
Example #18
0
        private async Task EvaluateAsync()
        {
            try {
                await TaskUtilities.SwitchToBackgroundThread();

                const REvaluationResultProperties properties = ClassesProperty | ExpressionProperty | TypeNameProperty | DimProperty | LengthProperty;

                var result = await _rSession.TryEvaluateAndDescribeAsync(_evaluation.Expression, properties, null);

                var wrapper = new VariableViewModel(result, _services);

                _services.MainThread().Post(() => SetEvaluation(wrapper));
            } catch (Exception ex) {
                _services.MainThread().Post(() => SetError(ex.Message));
            }
        }
Example #19
0
        protected async Task <IRValueInfo> EvaluateAsync(string expression, REvaluationResultProperties fields, string repr)
        {
            var result = await Evaluator.EvaluateAsync(expression, fields, repr);

            var error = result as IRErrorInfo;

            if (error != null)
            {
                await VsAppShell.Current.SwitchToMainThreadAsync();

                VsAppShell.Current.ShowErrorMessage(error.ErrorText);
                return(null);
            }

            return(result as IRValueInfo);
        }
Example #20
0
        private async Task EvaluateAsync()
        {
            try {
                await TaskUtilities.SwitchToBackgroundThread();

                const REvaluationResultProperties properties = ClassesProperty | ExpressionProperty | TypeNameProperty | DimProperty | LengthProperty;

                var result = await _rSession.TryEvaluateAndDescribeAsync(_evaluation.Expression, properties, null);

                var wrapper = new VariableViewModel(result, _aggregator);

                VsAppShell.Current.DispatchOnUIThread(() => SetEvaluation(wrapper));
            } catch (Exception ex) {
                VsAppShell.Current.DispatchOnUIThread(() => SetError(ex.Message));
            }
        }
Example #21
0
        protected override async Task <IReadOnlyList <IRSessionDataObject> > GetChildrenAsyncInternal()
        {
            List <IRSessionDataObject> result = null;

            var valueEvaluation = DebugEvaluation as IRValueInfo;

            if (valueEvaluation == null)
            {
                Debug.Assert(false, $"{nameof(VariableViewModel)} result type is not {typeof(IRValueInfo)}");
                return(result);
            }

            if (valueEvaluation.HasChildren)
            {
                await TaskUtilities.SwitchToBackgroundThread();

                REvaluationResultProperties properties =
                    ExpressionProperty |
                    AccessorKindProperty |
                    TypeNameProperty |
                    ClassesProperty |
                    LengthProperty |
                    SlotCountProperty |
                    AttributeCountProperty |
                    DimProperty |
                    FlagsProperty |
                    CanCoerceToDataFrameProperty |
                    (Services.GetService <IRToolsSettings>().EvaluateActiveBindings ? ComputedValueProperty : 0);
                IReadOnlyList <IREvaluationResultInfo> children = await valueEvaluation.DescribeChildrenAsync(properties, Repr, MaxChildrenCount);

                result = new List <IRSessionDataObject>();
                var aggregator = VsAppShell.Current.GetService <IObjectDetailsViewerAggregator>();
                for (int i = 0; i < children.Count; i++)
                {
                    result.Add(new VariableViewModel(children[i], Services, i, GetMaxChildrenCount(children[i])));
                }

                // return children can be less than value's length in some cases e.g. missing parameter
                if (valueEvaluation.Length > result.Count &&
                    (valueEvaluation.Length > MaxChildrenCount))
                {
                    result.Add(VariableViewModel.Ellipsis); // insert dummy child to indicate truncation in UI
                }
            }

            return(result);
        }
Example #22
0
        public async Task <IREvaluationResultInfo> EvaluateAsync(string expression, REvaluationResultProperties fields, string repr = null)
        {
            await TaskUtilities.SwitchToBackgroundThread();

            repr = repr ?? RValueRepresentations.Str();

            // Don't cache sessions since they can be disposed, expecially the debug session
            // when host is restarts or gets re-created in tests
            var rSession = _rSessionProvider.GetInteractiveWindowRSession();

            var frames = await rSession.TracebackAsync();

            if (frames == null || frames.Count == 0)
            {
                throw new InvalidOperationException("Debugger frames stack is empty");
            }
            return(await frames.Last().TryEvaluateAndDescribeAsync(expression, fields, repr) as IRValueInfo);
        }
Example #23
0
        private async Task SetRootModelAsync(REnvironment env)
        {
            await TaskUtilities.SwitchToBackgroundThread();

            const REvaluationResultProperties properties = ClassesProperty | ExpressionProperty | TypeNameProperty | DimProperty | LengthProperty;

            IRValueInfo result;

            try {
                result = await _session.EvaluateAndDescribeAsync(env.EnvironmentExpression, properties, null);
            } catch (RException ex) {
                VsAppShell.Current.DispatchOnUIThread(() => SetRootNode(VariableViewModel.Error(ex.Message)));
                return;
            }

            var wrapper       = new VariableViewModel(result, _aggregator);
            var rootNodeModel = new VariableNode(_settings, wrapper);

            VsAppShell.Current.DispatchOnUIThread(() => _rootNode.Model = rootNodeModel);
        }
Example #24
0
        private IReadOnlyList <IREvaluationResultInfo> CreateChildren() =>
        TaskExtensions.RunSynchronouslyOnUIThread(async ct => {
            var valueResult = EvaluationResult as IRValueInfo;
            if (valueResult == null)
            {
                return(new IREvaluationResultInfo[0]);
            }

            REvaluationResultProperties properties = RToolsSettings.Current.EvaluateActiveBindings ? REvaluationResultProperties.ComputedValueProperty : 0;
            properties  |= PrefetchedProperties;
            var children = await valueResult.DescribeChildrenAsync(properties, Repr, ChildrenMaxCount, ct);

            // Children of environments do not have any meaningful order, so sort them by name.
            if (valueResult.TypeName == "environment")
            {
                children = children.OrderBy(er => er.Name).ToArray();
            }

            return(children);
        });
Example #25
0
        /// <summary>
        /// Like <see cref="TryEvaluateAndDescribeAsync(IRSession, string, string, string, REvaluationResultProperties, string, CancellationToken)"/>,
        /// but throws <see cref="RException"/> if result is an <see cref="IRErrorInfo"/>.
        /// </summary>
        public static async Task <IRValueInfo> EvaluateAndDescribeAsync(
            this IRExpressionEvaluator session,
            string environmentExpression,
            string expression,
            string name,
            REvaluationResultProperties properties,
            string repr,
            CancellationToken cancellationToken = default(CancellationToken)
            )
        {
            var info = await session.TryEvaluateAndDescribeAsync(environmentExpression, expression, name, properties, repr, cancellationToken);

            var error = info as IRErrorInfo;

            if (error != null)
            {
                throw new RException(error.ErrorText);
            }

            Debug.Assert(info is IRValueInfo);
            return((IRValueInfo)info);
        }
Example #26
0
        public async Task <IREvaluationResultInfo> EvaluateAsync(string rScript)
        {
            // One eval at a time
            await _sem.WaitAsync();

            try {
                var frames = await Session.TracebackAsync();

                var frame = frames.FirstOrDefault(f => f.Index == 0);

                const REvaluationResultProperties properties = ClassesProperty | ExpressionProperty | TypeNameProperty | DimProperty | LengthProperty;
                var result = await frame.TryEvaluateAndDescribeAsync(rScript, properties, RValueRepresentations.Str());

                var globalResult = await frame.TryEvaluateAndDescribeAsync("base::environment()", properties, RValueRepresentations.Str());

                _globalEnv = new VariableViewModel(globalResult, VsAppShell.Current.ExportProvider.GetExportedValue <IObjectDetailsViewerAggregator>());

                return(result);
            } finally {
                _sem.Release();
            }
        }
Example #27
0
        /// <summary>
        /// Computes the children of the object represented by the given expression, and returns a collection of
        /// evaluation objects describing each child.
        /// See <see cref="RSessionExtensions.TryEvaluateAndDescribeAsync"/> for the meaning of other parameters.
        /// </summary>
        /// <param name="evaluateActiveBindings">Passes a flag to R to evalaute bindings based on RTools Settings.</param>
        /// <param name="maxCount">If not <see langword="null"/>, return at most that many children.</param>
        /// <remarks>
        /// <para>
        /// The resulting collection has an item for every child. If the child could be retrieved, and represents
        /// a value, the corresponding item is an <see cref="IRValueInfo"/> instance. If the child represents
        /// a promise, the promise is not forced, and the item is an <see cref="IRPromiseInfo"/> instance. If the
        /// child represents an active binding, the binding may be evaluated to retrieve the value, and the item is
        /// an <see cref="IRActiveBindingInfo"/> instance. If the child could not be retrieved, the item is an
        /// <see cref="IRErrorInfo"/> instance describing the error that prevented its retrieval.
        /// </para>
        /// <para>
        /// Where order matters (e.g. for children of atomic vectors and lists), children are returned in that order.
        /// Otherwise, the order is undefined. If an object has both ordered and unordered children (e.g. it is a vector
        /// with slots), then it is guaranteed that each group is reported as a contiguous sequence within the returned
        /// collection, and order is honored within each group; but groups themselves are not ordered relative to each other.
        /// </para>
        /// </remarks>
        /// <exception cref="RException">
        /// Raised if the operation fails as a whole (note that if only specific children cannot be retrieved, those
        /// children are represented by <see cref="IRErrorInfo"/> instances in the returned collection instead).
        /// </exception>
        public static async Task <IReadOnlyList <IREvaluationResultInfo> > DescribeChildrenAsync(
            this IRExpressionEvaluator session,
            string environmentExpression,
            string expression,
            REvaluationResultProperties properties,
            string repr,
            int?maxCount = null,
            CancellationToken cancellationToken = default(CancellationToken)
            )
        {
            await TaskUtilities.SwitchToBackgroundThread();

            var call      = Invariant($"rtvs:::describe_children({expression.ToRStringLiteral()}, {environmentExpression}, {properties.ToRVector()}, {maxCount}, {repr})");
            var jChildren = await session.EvaluateAsync <JArray>(call, REvaluationKind.Normal, cancellationToken);

            Trace.Assert(
                jChildren.Children().All(t => t is JObject),
                Invariant($"rtvs:::describe_children(): object of objects expected.\n\n{jChildren}"));

            var children = new List <REvaluationResultInfo>();

            foreach (var child in jChildren)
            {
                var childObject = (JObject)child;
                Trace.Assert(
                    childObject.Count == 1,
                    Invariant($"rtvs:::describe_children(): each object is expected contain one object\n\n"));
                foreach (var kv in childObject)
                {
                    var name        = kv.Key;
                    var jEvalResult = (JObject)kv.Value;
                    var evalResult  = REvaluationResultInfo.Parse(session, environmentExpression, name, jEvalResult);
                    children.Add(evalResult);
                }
            }

            return(children);
        }
Example #28
0
        /// <summary>
        /// Evaluates an R expresion in the specified environment, and returns an object describing the result.
        /// </summary>
        /// <param name="environmentExpression">
        /// R expression designating the environment in which <paramref name="expression"/> will be evaluated.
        /// </param>
        /// <param name="expression">Expression to evaluate.</param>
        /// <param name="name"><see cref="IREvaluationResultInfo.Name"/> of the returned evaluation result.</param>
        /// <param name="properties">Specifies which <see cref="IREvaluationResultInfo"/> properties should be present in the result.</param>
        /// <param name="repr">
        /// An R expression that must evaluate to a function that takes an R value as its sole argument, and returns the
        /// string representation of that argument as a single-element character vector. The representation is stored in
        /// <see cref="IRValueInfo.Representation"/> property of the produced result. If this argument is
        /// <see langword="null"/>, no representation is computed, and <see cref="IRValueInfo.Representation"/>
        /// will also be <see langword="null"/>.
        /// Use helper properties and methods in <see cref="RValueRepresentations"/> to obtain an appropriate expression
        /// for standard R functions such as <c>deparse()</c> or <c>str()</c>.
        /// </param>
        /// <remarks>
        /// <returns>
        /// If evaluation succeeded, an instance of <see cref="IRValueInfo"/> describing the resulting value.
        /// If evaluation failed with an error, an instance of <see cref="IRErrorInfo"/> describing the error.
        /// This method never returns <see cref="IRActiveBindingInfo"/> or <see cref="IRPromiseInfo"/>.
        /// </returns>
        public static async Task<IREvaluationResultInfo> TryEvaluateAndDescribeAsync(
            this IRSession session,
            string environmentExpression,
            string expression,
            string name,
            REvaluationResultProperties properties,
            string repr,
            CancellationToken cancellationToken = default(CancellationToken)
        ) {
            if (environmentExpression == null) {
                throw new ArgumentNullException(nameof(environmentExpression));
            }
            if (expression == null) {
                throw new ArgumentNullException(nameof(expression));
            }

            await TaskUtilities.SwitchToBackgroundThread();

            environmentExpression = environmentExpression ?? "NULL";
            var code = Invariant($"rtvs:::eval_and_describe({expression.ToRStringLiteral()}, ({environmentExpression}),, {properties.ToRVector()},, {repr})");
            var result = await session.EvaluateAsync<JObject>(code, REvaluationKind.Normal, cancellationToken);
            return REvaluationResultInfo.Parse(session, environmentExpression, name, result);
        }
Example #29
0
        /// <summary>
        /// Like <see cref="TryEvaluateAndDescribeAsync(IRSession, string, string, string, REvaluationResultProperties, string, CancellationToken)"/>,
        /// but throws <see cref="RException"/> if result is an <see cref="IRErrorInfo"/>.
        /// </summary>
        public static async Task<IRValueInfo> EvaluateAndDescribeAsync(
            this IRSession session,
            string environmentExpression,
            string expression,
            string name,
            REvaluationResultProperties properties,
            string repr,
            CancellationToken cancellationToken = default(CancellationToken)
        ) {
            var info = await session.TryEvaluateAndDescribeAsync(environmentExpression, expression, name, properties, repr, cancellationToken);

            var error = info as IRErrorInfo;
            if (error != null) {
                throw new RException(error.ErrorText);
            }

            Debug.Assert(info is IRValueInfo);
            return (IRValueInfo)info;
        }
Example #30
0
 private Task <IRValueInfo> EvaluateAndDescribeAsync(string expression, REvaluationResultProperties properties, CancellationToken cancellationToken = default(CancellationToken))
 => _session.EvaluateAndDescribeAsync(expression, properties, RValueRepresentations.Str(), cancellationToken);
Example #31
0
 /// <summary>
 /// Produces an object describing this frame's environment. <see cref="REvaluationResultInfoExtensions.DescribeChildrenAsync"/>
 /// method can then be used to retrieve the variables in the frame.
 /// </summary>
 /// <param name="properties">
 /// Which properties of the returned object should be provided. Note that it should include at least the following flags
 /// argument value in order for <see cref="REvaluationResultInfoExtensions.DescribeChildrenAsync"/> to be working. 
 /// </param>
 /// <remarks>
 /// <para>
 /// There is no guarantee that the returned evaluation result is <see cref="IRValueInfo"/>. Retrieving the frame environment involves
 /// evaluating <see cref="EnvironmentExpression"/>, and like any evaluation, it can fail. Caller should check for <see cref="IRErrorInfo"/>
 /// and handle it accordingly. However, it is never <see cref="IRPromiseInfo"/> or <see cref="IRActiveBindingInfo"/>.
 /// </para>
 /// <para>
 /// If this method is called on a stale frame (i.e if call stack has changed since the <see cref="RSessionExtensions.TracebackAsync"/>
 /// call that produced this frame), the result is undefined, and can be an error result, or contain unrelated data.
 /// </para>
 /// </remarks>
 public static Task<IRValueInfo> DescribeEnvironmentAsync(
     this IRStackFrame frame,
     REvaluationResultProperties properties,
     CancellationToken cancellationToken = default(CancellationToken)
 ) {
     properties |= ExpressionProperty | LengthProperty | AttributeCountProperty | FlagsProperty;
     return frame.EvaluateAndDescribeAsync("base::environment()", properties, null, cancellationToken);
 }
Example #32
0
 /// <summary>
 /// Same as <see cref="Microsoft.R.DataInspection.RSessionExtensions.TryEvaluateAndDescribeAsync(string, string, string, REvaluationResultProperties, int?, CancellationToken)"/>,
 /// but passes <see cref="EnvironmentExpression"/> of this frame as <c>environmentExpression</c> argument,
 /// </summary>
 public static Task<IREvaluationResultInfo> TryEvaluateAndDescribeAsync(
     this IRStackFrame frame,
     string expression,
     string name,
     REvaluationResultProperties properties,
     string repr,
     CancellationToken cancellationToken = default(CancellationToken)
 ) =>
     frame.Session.TryEvaluateAndDescribeAsync(frame.EnvironmentExpression, expression, name, properties, repr, cancellationToken);
Example #33
0
 /// <summary>
 /// Same as <see cref="EvaluateAndDescribeAsync(IRStackFrame, string, string, REvaluationResultProperties, string, CancellationToken)"/>,
 /// but uses <see langword="null"/> for <c>name</c>.
 /// </summary>
 public static Task<IRValueInfo> EvaluateAndDescribeAsync(
     this IRStackFrame frame,
     string expression,
     REvaluationResultProperties properties,
     string repr,
     CancellationToken cancellationToken = default(CancellationToken)
 ) =>
     frame.EvaluateAndDescribeAsync(expression, null, properties, repr, cancellationToken);
Example #34
0
 /// <summary>
 /// Like <see cref="RSessionExtensions.DescribeChildrenAsync"/>, but returns children of this environment.
 /// </summary>
 /// <remarks>
 /// If this method is called on a stale frame (i.e if call stack has changed since the <see cref="RSessionExtensions.TracebackAsync"/>
 /// call that produced this frame), the result is undefined - the method can throw <see cref="RException"/>, or produce meaningless
 /// output.
 /// </remarks>
 public static Task<IReadOnlyList<IREvaluationResultInfo>> DescribeChildrenAsync(
     this IRStackFrame frame,
     REvaluationResultProperties properties,
     string repr,
     int? maxCount = null,
     CancellationToken cancellationToken = default(CancellationToken)
 ) =>
     frame.Session.DescribeChildrenAsync(frame.EnvironmentExpression, "base::environment()", properties, repr, maxCount, cancellationToken);
Example #35
0
        /// <summary>
        /// Computes the children of the object represented by the given expression, and returns a collection of
        /// evaluation objects describing each child.
        /// See <see cref="RSessionExtensions.TryEvaluateAndDescribeAsync"/> for the meaning of other parameters.
        /// </summary>
        /// <param name="evaluateActiveBindings">Passes a flag to R to evalaute bindings based on RTools Settings.</param>
        /// <param name="maxCount">If not <see langword="null"/>, return at most that many children.</param>
        /// <remarks>
        /// <para>
        /// The resulting collection has an item for every child. If the child could be retrieved, and represents
        /// a value, the corresponding item is an <see cref="IRValueInfo"/> instance. If the child represents
        /// a promise, the promise is not forced, and the item is an <see cref="IRPromiseInfo"/> instance. If the
        /// child represents an active binding, the binding may be evaluated to retrieve the value, and the item is
        /// an <see cref="IRActiveBindingInfo"/> instance. If the child could not be retrieved, the item is an 
        /// <see cref="IRErrorInfo"/> instance describing the error that prevented its retrieval.
        /// </para>
        /// <para>
        /// Where order matters (e.g. for children of atomic vectors and lists), children are returned in that order.
        /// Otherwise, the order is undefined. If an object has both ordered and unordered children (e.g. it is a vector
        /// with slots), then it is guaranteed that each group is reported as a contiguous sequence within the returned
        /// collection, and order is honored within each group; but groups themselves are not ordered relative to each other.
        /// </para>
        /// </remarks>
        /// <exception cref="RException">
        /// Raised if the operation fails as a whole (note that if only specific children cannot be retrieved, those
        /// children are represented by <see cref="IRErrorInfo"/> instances in the returned collection instead).
        /// </exception>
        public static async Task<IReadOnlyList<IREvaluationResultInfo>> DescribeChildrenAsync(
            this IRSession session,
            string environmentExpression,
            string expression,
            REvaluationResultProperties properties,
            string repr,
            int? maxCount = null,
            CancellationToken cancellationToken = default(CancellationToken)
        ) {
            await TaskUtilities.SwitchToBackgroundThread();

            var call = Invariant($"rtvs:::describe_children({expression.ToRStringLiteral()}, {environmentExpression}, {properties.ToRVector()}, {maxCount}, {repr})");
            var jChildren = await session.EvaluateAsync<JArray>(call, REvaluationKind.Normal, cancellationToken);
            Trace.Assert(
                jChildren.Children().All(t => t is JObject),
                Invariant($"rtvs:::describe_children(): object of objects expected.\n\n{jChildren}"));

            var children = new List<REvaluationResultInfo>();
            foreach (var child in jChildren) {
                var childObject = (JObject)child;
                Trace.Assert(
                    childObject.Count == 1,
                    Invariant($"rtvs:::describe_children(): each object is expected contain one object\n\n"));
                foreach (var kv in childObject) {
                    var name = kv.Key;
                    var jEvalResult = (JObject)kv.Value;
                    var evalResult = REvaluationResultInfo.Parse(session, environmentExpression, name, jEvalResult);
                    children.Add(evalResult);
                }
            }

            return children;
        }
        public static string ToRVector(this REvaluationResultProperties properties)
        {
            var fieldNames = _mapping.Where(kv => properties.HasFlag(kv.Key)).Select(kv => "'" + kv.Value + "'");

            return(Invariant($"base::c({string.Join(", ", fieldNames)})"));
        }
Example #37
0
 /// <summary>
 /// Re-evaluates the expression that was used to create this evaluation object in its original context,
 /// but with a new representation function and properties.
 /// </summary>
 /// <remarks>
 /// Evaluating an expression always produces a regular value, never a promise or an active binding. Thus,
 /// this method can be used to compute the current value of an <see cref="IRActiveBindingInfo"/>, or force
 /// an <see cref="IRPromiseInfo"/>.
 /// </remarks>
 /// <exception cref="RException">Evaluation of the expression produced an error.</exception>
 public static Task <IRValueInfo> GetValueAsync(this IREvaluationResultInfo info, REvaluationResultProperties properties, string repr, CancellationToken cancellationToken = default(CancellationToken)) =>
 info.Evaluator.EvaluateAndDescribeAsync(info.EnvironmentExpression, info.Expression, info.Name, properties, repr, cancellationToken);
Example #38
0
 /// <summary>
 /// Re-evaluates the expression that was used to create this evaluation object in its original context,
 /// but with a new representation function and properties.
 /// </summary>
 /// <remarks>
 /// Evaluating an expression always produces a regular value, never a promise or an active binding. Thus,
 /// this method can be used to compute the current value of an <see cref="IRActiveBindingInfo"/>, or force
 /// an <see cref="IRPromiseInfo"/>.
 /// </remarks>
 /// <exception cref="RException">Evaluation of the expression produced an error.</exception>
 public static Task<IRValueInfo> GetValueAsync(this IREvaluationResultInfo info, REvaluationResultProperties properties, string repr, CancellationToken cancellationToken = default(CancellationToken)) =>
     info.Session.EvaluateAndDescribeAsync(info.EnvironmentExpression, info.Expression, info.Name, properties, repr, cancellationToken);