Permalink
Browse files

Move Expression Evaluator to Open (changeset 1411117)

  • Loading branch information...
dotnet-bot authored and RoslynTeam committed Feb 5, 2015
1 parent ccb1afd commit 6f53207a6f0c20db549b303cc37b4473ef3e7a83
Showing 327 changed files with 180,121 additions and 0 deletions.
@@ -0,0 +1,69 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
+{
+ internal sealed class EEMethodBinder : Binder
+ {
+ private readonly MethodSymbol _containingMethod;
+ private readonly int _parameterOffset;
+ private readonly ImmutableArray<ParameterSymbol> _targetParameters;
+ private readonly Binder _sourceBinder;
+
+ internal EEMethodBinder(EEMethodSymbol method, MethodSymbol containingMethod, Binder next) : base(next)
+ {
+ // There are a lot of method symbols floating around and we're doing some subtle things with them.
+ // 1) method is the EEMethodSymbol that we're going to synthesize and hand to the debugger to evaluate.
+ // 2) containingMethod is the method that we are conceptually in, e.g. the method containing the
+ // lambda that is on top of the call stack. Any type parameters will have been replaced with the
+ // corresponding type parameters from (1) and its containing type.
+ // 3) method.SubstitutedSourceMethod is the method that we are actually in, e.g. a lambda method in
+ // a display class. Any type parameters will have been replaced with the corresponding type parameters
+ // from (1).
+ // So why do we need all these methods?
+ // 1) gives us the parameters that we need to actually bind to (it's no good to bind to the symbols
+ // owned by (2) or (3)). Also, it happens to contain (3), so we don't need to pass (3) explicitly.
+ // 2) is where we want to pretend we're binding expressions, so we make it the containing symbol of
+ // this binder.
+ // 3) is where we'll pretend to be for the purposes of looking up parameters by name. However, any
+ // parameters we bind to from (3) will be replaced by the corresponding parameters from (1).
+
+ _containingMethod = containingMethod;
+ var substitutedSourceMethod = method.SubstitutedSourceMethod;
+ _parameterOffset = substitutedSourceMethod.IsStatic ? 0 : 1;
+ _targetParameters = method.Parameters;
+ _sourceBinder = new InMethodBinder(substitutedSourceMethod, new BuckStopsHereBinder(next.Compilation));
+ }
+
+ internal override void LookupSymbolsInSingleBinder(LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
+ {
+ _sourceBinder.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, this, diagnose, ref useSiteDiagnostics);
+
+ var symbols = result.Symbols;
+ for (int i = 0; i < symbols.Count; i++)
+ {
+ // Type parameters requiring mapping to the target type and
+ // should be found by WithMethodTypeParametersBinder instead.
+ var parameter = (ParameterSymbol)symbols[i];
+ Debug.Assert(parameter.ContainingSymbol == _sourceBinder.ContainingMemberOrLambda);
+ symbols[i] = _targetParameters[parameter.Ordinal + _parameterOffset];
+ }
+ }
+
+ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo info, LookupOptions options, Binder originalBinder)
+ {
+ throw new NotImplementedException();
+ }
+
+ internal override Symbol ContainingMemberOrLambda
+ {
+ get { return _containingMethod; }
+ }
+ }
+}
@@ -0,0 +1,133 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Globalization;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.ExpressionEvaluator;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
+{
+ internal sealed class PlaceholderLocalBinder : LocalScopeBinder
+ {
+ private readonly InspectionContext _inspectionContext;
+ private readonly TypeNameDecoder<PEModuleSymbol, TypeSymbol> _typeNameDecoder;
+ private readonly CSharpSyntaxNode _syntax;
+ private readonly MethodSymbol _containingMethod;
+
+ internal PlaceholderLocalBinder(
+ InspectionContext inspectionContext,
+ TypeNameDecoder<PEModuleSymbol, TypeSymbol> typeNameDecoder,
+ CSharpSyntaxNode syntax,
+ MethodSymbol containingMethod,
+ Binder next) :
+ base(next)
+ {
+ _inspectionContext = inspectionContext;
+ _typeNameDecoder = typeNameDecoder;
+ _syntax = syntax;
+ _containingMethod = containingMethod;
+ }
+
+ internal sealed override void LookupSymbolsInSingleBinder(
+ LookupResult result,
+ string name,
+ int arity,
+ ConsList<Symbol> basesBeingResolved,
+ LookupOptions options,
+ Binder originalBinder,
+ bool diagnose,
+ ref HashSet<DiagnosticInfo> useSiteDiagnostics)
+ {
+ if ((options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.NamespacesOrTypesOnly | LookupOptions.LabelsOnly)) != 0)
+ {
+ return;
+ }
+
+ var local = this.LookupPlaceholder(name);
+ if ((object)local == null)
+ {
+ base.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);
+ }
+ else
+ {
+ result.MergeEqual(this.CheckViability(local, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved));
+ }
+ }
+
+ protected sealed override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo info, LookupOptions options, Binder originalBinder)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override ImmutableArray<LocalSymbol> BuildLocals()
+ {
+ var builder = ArrayBuilder<LocalSymbol>.GetInstance();
+ var declaration = _syntax as LocalDeclarationStatementSyntax;
+ if (declaration != null)
+ {
+ var kind = declaration.IsConst ? LocalDeclarationKind.Constant : LocalDeclarationKind.RegularVariable;
+ foreach (var variable in declaration.Declaration.Variables)
+ {
+ var local = SourceLocalSymbol.MakeLocal(_containingMethod, this, declaration.Declaration.Type, variable.Identifier, kind, variable.Initializer);
+ builder.Add(local);
+ }
+ }
+ return builder.ToImmutableAndFree();
+ }
+
+ private PlaceholderLocalSymbol LookupPlaceholder(string name)
+ {
+ if (name.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
+ {
+ var valueText = name.Substring(2);
+ ulong address;
+ if (!ulong.TryParse(valueText, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out address))
+ {
+ // Invalid value should have been caught by Lexer.
+ throw ExceptionUtilities.UnexpectedValue(valueText);
+ }
+ return new ObjectAddressLocalSymbol(_containingMethod, name, this.Compilation.GetSpecialType(SpecialType.System_Object), address);
+ }
+
+ PseudoVariableKind kind;
+ string id;
+ int index;
+ if (!PseudoVariableUtilities.TryParseVariableName(name, caseSensitive: true, kind: out kind, id: out id, index: out index))
+ {
+ return null;
+ }
+
+ var typeName = PseudoVariableUtilities.GetTypeName(_inspectionContext, kind, id, index);
+ if (typeName == null)
+ {
+ return null;
+ }
+
+ Debug.Assert(typeName.Length > 0);
+
+ var type = _typeNameDecoder.GetTypeSymbolForSerializedType(typeName);
+ Debug.Assert((object)type != null);
+
+ switch (kind)
+ {
+ case PseudoVariableKind.Exception:
+ case PseudoVariableKind.StowedException:
+ return new ExceptionLocalSymbol(_containingMethod, id, type);
+ case PseudoVariableKind.ReturnValue:
+ return new ReturnValueLocalSymbol(_containingMethod, id, type, index);
+ case PseudoVariableKind.ObjectId:
+ return new ObjectIdLocalSymbol(_containingMethod, type, id, isWritable: false);
+ case PseudoVariableKind.DeclaredLocal:
+ return new ObjectIdLocalSymbol(_containingMethod, type, id, isWritable: true);
+ default:
+ throw ExceptionUtilities.UnexpectedValue(kind);
+ }
+ }
+ }
+}
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Roslyn.Utilities;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+
+namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
+{
+ internal sealed class WithTypeArgumentsBinder : WithTypeParametersBinder
+ {
+ private readonly ImmutableArray<TypeSymbol> _typeArguments;
+ private MultiDictionary<string, TypeParameterSymbol> _lazyTypeParameterMap;
+
+ internal WithTypeArgumentsBinder(ImmutableArray<TypeSymbol> typeArguments, Binder next)
+ : base(next)
+ {
+ Debug.Assert(!typeArguments.IsDefaultOrEmpty);
+ Debug.Assert(typeArguments.All(ta => ta.Kind == SymbolKind.TypeParameter));
+ _typeArguments = typeArguments;
+ }
+
+ protected override MultiDictionary<string, TypeParameterSymbol> TypeParameterMap
+ {
+ get
+ {
+ if (_lazyTypeParameterMap == null)
+ {
+ var result = new MultiDictionary<string, TypeParameterSymbol>();
+ foreach (TypeParameterSymbol tps in _typeArguments)
+ {
+ result.Add(tps.Name, tps);
+ }
+ Interlocked.CompareExchange(ref _lazyTypeParameterMap, result, null);
+ }
+ return _lazyTypeParameterMap;
+ }
+ }
+
+ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo result, LookupOptions options, Binder originalBinder)
+ {
+ if (CanConsiderTypeParameters(options))
+ {
+ foreach (var parameter in _typeArguments)
+ {
+ if (originalBinder.CanAddLookupSymbolInfo(parameter, options, null))
+ {
+ result.AddSymbol(parameter, parameter.Name, 0);
+ }
+ }
+ }
+ }
+ }
+}
@@ -0,0 +1,85 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using Microsoft.CodeAnalysis.ExpressionEvaluator;
+using Microsoft.VisualStudio.Debugger;
+using Microsoft.VisualStudio.Debugger.Clr;
+using Microsoft.VisualStudio.Debugger.Evaluation;
+
+namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
+{
+ [DkmReportNonFatalWatsonException(ExcludeExceptionType = typeof(NotImplementedException)), DkmContinueCorruptingException]
+ internal sealed class CSharpExpressionCompiler : ExpressionCompiler
+ {
+ private static readonly DkmCompilerId s_compilerId = new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.CSharp);
+
+ internal override DiagnosticFormatter DiagnosticFormatter
+ {
+ get { return DiagnosticFormatter.Instance; }
+ }
+
+ internal override DkmCompilerId CompilerId
+ {
+ get { return s_compilerId; }
+ }
+
+ internal override EvaluationContextBase CreateTypeContext(
+ DkmClrAppDomain appDomain,
+ ImmutableArray<MetadataBlock> metadataBlocks,
+ Guid moduleVersionId,
+ int typeToken)
+ {
+ var previous = appDomain.GetDataItem<CSharpMetadataContext>();
+ var context = EvaluationContext.CreateTypeContext(
+ appDomain.GetDataItem<CSharpMetadataContext>(),
+ metadataBlocks,
+ moduleVersionId,
+ typeToken);
+
+ // New type context is not attached to the AppDomain since it is less
+ // re-usable than the previous attached method context. (We could hold
+ // on to it if we don't have a previous method context but it's unlikely
+ // that we evaluated a type-level expression before a method-level.)
+ Debug.Assert(previous == null || context != previous.EvaluationContext);
+
+ return context;
+ }
+
+ internal override EvaluationContextBase CreateMethodContext(
+ DkmClrAppDomain appDomain,
+ ImmutableArray<MetadataBlock> metadataBlocks,
+ Lazy<ImmutableArray<AssemblyReaders>> unusedLazyAssemblyReaders,
+ object symReader,
+ Guid moduleVersionId,
+ int methodToken,
+ int methodVersion,
+ int ilOffset,
+ int localSignatureToken)
+ {
+ var previous = appDomain.GetDataItem<CSharpMetadataContext>();
+ var context = EvaluationContext.CreateMethodContext(
+ previous,
+ metadataBlocks,
+ symReader,
+ moduleVersionId,
+ methodToken,
+ methodVersion,
+ ilOffset,
+ localSignatureToken);
+
+ if (previous == null || context != previous.EvaluationContext)
+ {
+ appDomain.SetDataItem(DkmDataCreationDisposition.CreateAlways, new CSharpMetadataContext(context));
+ }
+
+ return context;
+ }
+
+ internal override bool RemoveDataItem(DkmClrAppDomain appDomain)
+ {
+ return appDomain.RemoveDataItem<CSharpMetadataContext>();
+ }
+ }
+}
Oops, something went wrong.

0 comments on commit 6f53207

Please sign in to comment.