Skip to content

Commit

Permalink
Move Expression Evaluator to Open (changeset 1411117)
Browse files Browse the repository at this point in the history
  • Loading branch information
dotnet-bot authored and RoslynTeam committed Feb 5, 2015
1 parent ccb1afd commit 6f53207
Show file tree
Hide file tree
Showing 327 changed files with 180,121 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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; }
}
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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>();
}
}
}
Loading

0 comments on commit 6f53207

Please sign in to comment.