/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Collections.ObjectModel; namespace dnSpy.Contracts.Debugger.Evaluation { /// /// Expression evaluator /// public abstract class DbgExpressionEvaluator { /// /// Gets the language /// public abstract DbgLanguage Language { get; } /// /// Creates evaluator state used to cache data that is needed to evaluate an expression /// /// public abstract object? CreateExpressionEvaluatorState(); /// /// Evaluates an expression. The returned is automatically closed when its runtime continues. /// /// Evaluation info /// Expression to evaluate /// Options /// State created by or null to store the state in 's context /// public abstract DbgEvaluationResult Evaluate(DbgEvaluationInfo evalInfo, string expression, DbgEvaluationOptions options, object? state); /// /// Assigns the value of an expression to another expression /// /// Evaluation info /// Target expression (lhs) /// Source expression (rhs) /// Options /// public abstract DbgEEAssignmentResult Assign(DbgEvaluationInfo evalInfo, string expression, string valueExpression, DbgEvaluationOptions options); } /// /// Evaluation options /// [Flags] public enum DbgEvaluationOptions { /// /// No bit is set /// None = 0, /// /// Set if it's an expression, false if it's a statement /// Expression = 0x00000001, /// /// Fail if the expression causes side effects, eg. method calls /// NoSideEffects = 0x00000002, /// /// Don't allow function evaluations (calling code in debugged process) /// NoFuncEval = 0x00000004, /// /// Don't create a name/expression (only used by value nodes) /// NoName = 0x00000008, /// /// Use only the locals that exist in the metadata. Don't show captured variables, show their display class variables instead /// RawLocals = 0x00000010, } /// /// Evaluation result flags /// [Flags] public enum DbgEvaluationResultFlags { /// /// No bit is set /// None = 0, /// /// The expression causes side effects /// SideEffects = 0x00000001, /// /// The result is read-only /// ReadOnly = 0x00000002, /// /// It's a boolean expression /// BooleanExpression = 0x00000004, /// /// The value is a thrown exception /// ThrownException = 0x00000008, } /// /// Evaluation result /// public readonly struct DbgEvaluationResult { /// /// Gets the value or null if there was an error /// public DbgValue? Value { get; } /// /// Gets the format specifiers /// public ReadOnlyCollection FormatSpecifiers { get; } /// /// Gets the flags /// public DbgEvaluationResultFlags Flags { get; } /// /// true if is a thrown exception /// public bool IsThrownException => (Flags & DbgEvaluationResultFlags.ThrownException) != 0; /// /// Gets the error or null if none /// public string? Error { get; } static readonly ReadOnlyCollection emptyFormatSpecifiers = new ReadOnlyCollection(Array.Empty()); /// /// Constructor /// /// Value /// Format specifiers or null /// Flags public DbgEvaluationResult(DbgValue value, ReadOnlyCollection? formatSpecifiers, DbgEvaluationResultFlags flags) { Value = value ?? throw new ArgumentNullException(nameof(value)); FormatSpecifiers = formatSpecifiers ?? emptyFormatSpecifiers; Flags = flags; Error = null; } /// /// Constructor /// /// Error message /// Format specifiers or null /// Flags public DbgEvaluationResult(string error, ReadOnlyCollection? formatSpecifiers = null, DbgEvaluationResultFlags flags = 0) { Value = null; FormatSpecifiers = formatSpecifiers ?? emptyFormatSpecifiers; Flags = flags; Error = error ?? throw new ArgumentNullException(nameof(error)); } } /// /// Assignment result flags /// [Flags] public enum DbgEEAssignmentResultFlags { /// /// No bit is set /// None = 0, /// /// The error is from the compiler and no debuggee code was executed /// CompilerError = 0x00000001, /// /// Code in the debuggee was executed /// ExecutedCode = 0x00000002, } /// /// Expression evaluator assignment result /// public readonly struct DbgEEAssignmentResult { /// /// Error message or null /// public string? Error { get; } /// /// Gets the flags /// public DbgEEAssignmentResultFlags Flags { get; } /// /// true if the error is from the compiler and no debuggee code was executed /// public bool IsCompilerError => (Flags & DbgEEAssignmentResultFlags.CompilerError) != 0; /// /// Constructor /// /// Result flags /// Error message or null public DbgEEAssignmentResult(DbgEEAssignmentResultFlags flags, string? error) { Flags = flags; Error = error; } } }