本文整理汇总了C#中Microsoft.CodeAnalysis.CSharp.BoundExpressionStatement类的典型用法代码示例。如果您正苦于以下问题:C# BoundExpressionStatement类的具体用法?C# BoundExpressionStatement怎么用?C# BoundExpressionStatement使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
BoundExpressionStatement类属于Microsoft.CodeAnalysis.CSharp命名空间,在下文中一共展示了BoundExpressionStatement类的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C#代码示例。
示例1: VisitExpressionStatement
// All nodes with a single child expression are rewritten in the same manner.
//
// If the node is an expression and the child contains an await expression, then the rewriting transforms:
// Expression(Spill(sideEffects, Value))
// to:
// Spill(sideEffects, Expression(Value))
//
// If the node is a statement and the child contains an await expression, then the rewriting transforms:
// ExpressionStatement(Spill(sideEffects, Value))
// to:
// Block(sideEffects, ExpressionStatement(Value))
//
// If the child expression does not contain an await expression then no rewriting is performed.
public override BoundNode VisitExpressionStatement(BoundExpressionStatement node)
{
BoundExpression expression = (BoundExpression)this.Visit(node.Expression);
if (expression.Kind != BoundKind.SpillSequence)
{
return node.Update(expression);
}
return RewriteSpillSequenceAsBlock((BoundSpillSequence)expression);
}
开发者ID:modulexcite,项目名称:pattern-matching-csharp,代码行数:25,代码来源:AwaitLoweringRewriterPass1_Unary.cs
示例2: RewriteLocalDeclaration
private BoundStatement RewriteLocalDeclaration(BoundLocalDeclaration originalOpt, SyntaxNode syntax, LocalSymbol localSymbol, BoundExpression rewrittenInitializer, bool hasErrors = false)
{
// A declaration of a local variable without an initializer has no associated IL.
// Simply remove the declaration from the bound tree. The local symbol will
// remain in the bound block, so codegen will make a stack frame location for it.
if (rewrittenInitializer == null)
{
return null;
}
// A declaration of a local constant also does nothing, even though there is
// an assignment. The value will be emitted directly where it is used. The
// local symbol remains in the bound block, but codegen will skip making a
// stack frame location for it. (We still need a symbol for it to stay
// around because we'll be generating debug info for it.)
if (localSymbol.IsConst)
{
if (!localSymbol.Type.IsReferenceType && localSymbol.ConstantValue == null)
{
// This can occur in error scenarios (e.g. bad imported metadata)
hasErrors = true;
}
else
{
return null;
}
}
// lowered local declaration node is associated with declaration (not whole statement)
// this is done to make sure that debugger stepping is same as before
var localDeclaration = syntax as LocalDeclarationStatementSyntax;
if (localDeclaration != null)
{
syntax = localDeclaration.Declaration.Variables[0];
}
BoundStatement rewrittenLocalDeclaration = new BoundExpressionStatement(
syntax,
new BoundAssignmentOperator(
syntax,
new BoundLocal(
syntax,
localSymbol,
null,
localSymbol.Type
),
rewrittenInitializer,
localSymbol.Type,
localSymbol.RefKind),
hasErrors);
return InstrumentLocalDeclarationIfNecessary(originalOpt, localSymbol, rewrittenLocalDeclaration);
}
开发者ID:XieShuquan,项目名称:roslyn,代码行数:53,代码来源:LocalRewriter_LocalDeclaration.cs
示例3: ConstructScriptConstructorBody
internal static ImmutableArray<BoundStatement> ConstructScriptConstructorBody(
BoundStatement loweredBody,
MethodSymbol constructor,
SynthesizedSubmissionFields previousSubmissionFields,
CSharpCompilation compilation)
{
// Script field initializers have to be emitted after the call to the base constructor because they can refer to "this" instance.
//
// Unlike regular field initializers, initializers of global script variables can access "this" instance.
// If the base class had a constructor that initializes its state a global variable would access partially initialized object.
// For this reason Script class must always derive directly from a class that has no state (System.Object).
CSharpSyntaxNode syntax = loweredBody.Syntax;
// base constructor call:
Debug.Assert((object)constructor.ContainingType.BaseTypeNoUseSiteDiagnostics == null || constructor.ContainingType.BaseTypeNoUseSiteDiagnostics.SpecialType == SpecialType.System_Object);
var objectType = constructor.ContainingAssembly.GetSpecialType(SpecialType.System_Object);
BoundExpression receiver = new BoundThisReference(syntax, constructor.ContainingType) { WasCompilerGenerated = true };
BoundStatement baseConstructorCall =
new BoundExpressionStatement(syntax,
new BoundCall(syntax,
receiverOpt: receiver,
method: objectType.InstanceConstructors[0],
arguments: ImmutableArray<BoundExpression>.Empty,
argumentNamesOpt: ImmutableArray<string>.Empty,
argumentRefKindsOpt: ImmutableArray<RefKind>.Empty,
isDelegateCall: false,
expanded: false,
invokedAsExtensionMethod: false,
argsToParamsOpt: ImmutableArray<int>.Empty,
resultKind: LookupResultKind.Viable,
type: objectType)
{ WasCompilerGenerated = true })
{ WasCompilerGenerated = true };
var statements = ArrayBuilder<BoundStatement>.GetInstance();
statements.Add(baseConstructorCall);
if (constructor.IsSubmissionConstructor)
{
// submission initialization:
MakeSubmissionInitialization(statements, syntax, constructor, previousSubmissionFields, compilation);
}
statements.Add(loweredBody);
return statements.ToImmutableAndFree();
}
开发者ID:rafaellincoln,项目名称:roslyn,代码行数:49,代码来源:MethodBodySynthesizer.cs
示例4: VisitExpressionStatement
public override BoundNode VisitExpressionStatement(BoundExpressionStatement node)
{
var syntax = node.Syntax;
var loweredExpression = VisitUnusedExpression(node.Expression);
if (loweredExpression == null)
{
// NOTE: not using a BoundNoOpStatement, since we don't want a nop to be emitted.
// CONSIDER: could use a BoundNoOpStatement (DevDiv #12943).
return BoundStatementList.Synthesized(syntax);
}
else
{
return AddSequencePoint(node.Update(loweredExpression));
}
}
开发者ID:riversky,项目名称:roslyn,代码行数:16,代码来源:LocalRewriter_ExpressionStatement.cs
示例5: InstrumentFieldOrPropertyInitializer
public override BoundStatement InstrumentFieldOrPropertyInitializer(BoundExpressionStatement original, BoundStatement rewritten)
{
rewritten = base.InstrumentExpressionStatement(original, rewritten);
CSharpSyntaxNode syntax = original.Syntax;
switch (syntax.Parent.Parent.Kind())
{
case SyntaxKind.VariableDeclarator:
var declaratorSyntax = (VariableDeclaratorSyntax)syntax.Parent.Parent;
return AddSequencePoint(declaratorSyntax, rewritten);
case SyntaxKind.PropertyDeclaration:
var declaration = (PropertyDeclarationSyntax)syntax.Parent.Parent;
return AddSequencePoint(declaration, rewritten);
default:
throw ExceptionUtilities.UnexpectedValue(syntax.Parent.Parent.Kind());
}
}
开发者ID:xeronith,项目名称:roslyn,代码行数:19,代码来源:DebugInfoInjector.cs
示例6: RewriteExpressionStatement
private BoundStatement RewriteExpressionStatement(BoundExpressionStatement node, bool suppressInstrumentation = false)
{
var loweredExpression = VisitUnusedExpression(node.Expression);
if (loweredExpression == null)
{
return null;
}
else
{
BoundStatement result = node.Update(loweredExpression);
if (!suppressInstrumentation && this.Instrument && !node.WasCompilerGenerated)
{
result = _instrumenter.InstrumentExpressionStatement(node, result);
}
return result;
}
}
开发者ID:Rickinio,项目名称:roslyn,代码行数:19,代码来源:LocalRewriter_ExpressionStatement.cs
示例7: InstrumentExpressionStatement
public override BoundStatement InstrumentExpressionStatement(BoundExpressionStatement original, BoundStatement rewritten)
{
rewritten = base.InstrumentExpressionStatement(original, rewritten);
if (original.IsConstructorInitializer())
{
switch (original.Syntax.Kind())
{
case SyntaxKind.ConstructorDeclaration:
// This is an implicit constructor initializer.
var decl = (ConstructorDeclarationSyntax)original.Syntax;
return new BoundSequencePointWithSpan(decl, rewritten, CreateSpanForConstructorInitializer(decl));
case SyntaxKind.BaseConstructorInitializer:
case SyntaxKind.ThisConstructorInitializer:
var init = (ConstructorInitializerSyntax)original.Syntax;
return new BoundSequencePointWithSpan(init, rewritten, CreateSpanForConstructorInitializer((ConstructorDeclarationSyntax)init.Parent));
}
}
return AddSequencePoint(rewritten);
}
开发者ID:xeronith,项目名称:roslyn,代码行数:21,代码来源:DebugInfoInjector.cs
示例8: VisitLocalDeconstructionDeclaration
public override BoundNode VisitLocalDeconstructionDeclaration(BoundLocalDeconstructionDeclaration node)
{
var syntax = node.Syntax;
var loweredExpression = VisitUnusedExpression(node.Assignment);
if (loweredExpression == null)
{
// NOTE: not using a BoundNoOpStatement, since we don't want a nop to be emitted.
// CONSIDER: could use a BoundNoOpStatement (DevDiv #12943).
return BoundStatementList.Synthesized(syntax);
}
else
{
BoundStatement result = new BoundExpressionStatement(loweredExpression.Syntax, loweredExpression, node.HasErrors);
result.WasCompilerGenerated = node.WasCompilerGenerated;
if (this.Instrument && !node.WasCompilerGenerated)
{
result = _instrumenter.InstrumentLocalDeconstructionDeclaration(node, result);
}
return result;
}
}
开发者ID:Rickinio,项目名称:roslyn,代码行数:23,代码来源:LocalRewriter_ExpressionStatement.cs
示例9: VisitExpressionStatement
public override BoundNode VisitExpressionStatement(BoundExpressionStatement node)
{
// ref assignments might be translated away (into nothing). If so just
// return no statement. The enclosing statement list will just omit it.
BoundExpression expression = (BoundExpression)this.Visit(node.Expression);
return (expression == null) ? null : node.Update(expression);
}
开发者ID:nagyist,项目名称:roslyn,代码行数:7,代码来源:StateMachineMethodToClassRewriter.cs
示例10: BindGlobalStatement
private static BoundInitializer BindGlobalStatement(Binder binder, StatementSyntax statementNode, DiagnosticBag diagnostics, bool isLast)
{
BoundStatement boundStatement = binder.BindStatement(statementNode, diagnostics);
// the result of the last global expression is assigned to the result storage for submission result:
if (binder.Compilation.IsSubmission && isLast && boundStatement.Kind == BoundKind.ExpressionStatement && !boundStatement.HasAnyErrors)
{
var submissionReturnType = binder.Compilation.GetSubmissionReturnType();
// insert an implicit conversion for the submission return type (if needed):
var expression = ((BoundExpressionStatement)boundStatement).Expression;
if ((object)expression.Type == null || expression.Type.SpecialType != SpecialType.System_Void)
{
expression = binder.GenerateConversionForAssignment(submissionReturnType, expression, diagnostics);
boundStatement = new BoundExpressionStatement(boundStatement.Syntax, expression, expression.HasErrors);
}
}
return new BoundGlobalStatementInitializer(statementNode, boundStatement);
}
开发者ID:SoumikMukherjeeDOTNET,项目名称:roslyn,代码行数:20,代码来源:Compiler.cs
示例11: BindMethodBody
// NOTE: can return null if the method has no body.
internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, bool generateDebugInfo, out ConsList<Imports> debugImports)
{
debugImports = null;
BoundStatement constructorInitializer = null;
BoundBlock body;
var compilation = method.DeclaringCompilation;
var sourceMethod = method as SourceMethodSymbol;
if ((object)sourceMethod != null)
{
if (sourceMethod.IsExtern)
{
if (sourceMethod.BlockSyntax == null)
{
// Generate warnings only if we are not generating ERR_ExternHasBody error
GenerateExternalMethodWarnings(sourceMethod, diagnostics);
}
return null;
}
else if (sourceMethod.IsParameterlessValueTypeConstructor(requireSynthesized: true))
{
// No body for default struct constructor.
return null;
}
var blockSyntax = sourceMethod.BlockSyntax;
if (blockSyntax != null)
{
var factory = compilation.GetBinderFactory(sourceMethod.SyntaxTree);
var inMethodBinder = factory.GetBinder(blockSyntax);
var binder = new ExecutableCodeBinder(blockSyntax, sourceMethod, inMethodBinder);
body = binder.BindBlock(blockSyntax, diagnostics);
if (generateDebugInfo)
{
debugImports = binder.ImportsList;
}
if (inMethodBinder.IsDirectlyInIterator)
{
foreach (var parameter in method.Parameters)
{
if (parameter.RefKind != RefKind.None)
{
diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]);
}
else if (parameter.Type.IsUnsafe())
{
diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]);
}
}
if (sourceMethod.IsUnsafe && compilation.Options.AllowUnsafe) // Don't cascade
{
diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, sourceMethod.Locations[0]);
}
if (sourceMethod.IsVararg)
{
// error CS1636: __arglist is not allowed in the parameter list of iterators
diagnostics.Add(ErrorCode.ERR_VarargsIterator, sourceMethod.Locations[0]);
}
}
}
else // for [if (blockSyntax != null)]
{
var property = sourceMethod.AssociatedSymbol as SourcePropertySymbol;
if ((object)property != null && property.IsAutoProperty)
{
return MethodBodySynthesizer.ConstructAutoPropertyAccessorBody(sourceMethod);
}
if (sourceMethod.IsPrimaryCtor)
{
body = null;
}
else
{
return null;
}
}
}
else
{
// synthesized methods should return their bound bodies
body = null;
}
// delegates have constructors but not constructor initializers
if (method.MethodKind == MethodKind.Constructor && !method.ContainingType.IsDelegateType())
{
var initializerInvocation = BindConstructorInitializer(method, diagnostics, compilation);
if (initializerInvocation != null)
{
constructorInitializer = new BoundExpressionStatement(initializerInvocation.Syntax, initializerInvocation) { WasCompilerGenerated = true };
Debug.Assert(initializerInvocation.HasAnyErrors || constructorInitializer.IsConstructorInitializer(), "Please keep this bound node in sync with BoundNodeExtensions.IsConstructorInitializer.");
}
}
//.........这里部分代码省略.........
开发者ID:SoumikMukherjeeDOTNET,项目名称:roslyn,代码行数:101,代码来源:Compiler.cs
示例12: BindExpressionStatement
public BoundExpressionStatement BindExpressionStatement(CSharpSyntaxNode node, ExpressionSyntax syntax, bool allowsAnyExpression, DiagnosticBag diagnostics)
{
BoundExpressionStatement expressionStatement;
var expression = BindValue(syntax, diagnostics, BindValueKind.RValue);
if (!allowsAnyExpression && !IsValidStatementExpression(syntax, expression))
{
if (!node.HasErrors)
{
Error(diagnostics, ErrorCode.ERR_IllegalStatement, syntax);
}
expressionStatement = new BoundExpressionStatement(node, expression, hasErrors: true);
}
else
{
expressionStatement = new BoundExpressionStatement(node, expression);
}
CheckForUnobservedAwaitable(expressionStatement, diagnostics);
return expressionStatement;
}
开发者ID:elemk0vv,项目名称:roslyn-1,代码行数:23,代码来源:Binder_Statements.cs
示例13: CheckForUnobservedAwaitable
/// <summary>
/// Report an error if this is an awaitable async method invocation that is not being awaited.
/// </summary>
/// <remarks>
/// The checks here are equivalent to StatementBinder::CheckForUnobservedAwaitable() in the native compiler.
/// </remarks>
private void CheckForUnobservedAwaitable(BoundExpressionStatement expressionStatement, DiagnosticBag diagnostics)
{
if (expressionStatement == null)
{
return;
}
BoundExpression expression = expressionStatement.Expression;
// If we don't have an expression or it doesn't have a type, just bail out
// now. Also, the dynamic type is always awaitable in an async method and
// could generate a lot of noise if we warned on it. Finally, we only want
// to warn on method calls, not other kinds of expressions.
if (expression == null
|| expression.Kind != BoundKind.Call
|| (object)expression.Type == null
|| expression.Type.IsDynamic()
|| expression.Type.SpecialType == SpecialType.System_Void)
{
return;
}
var call = (BoundCall)expression;
// First check if the target method is async.
if ((object)call.Method != null && call.Method.IsAsync)
{
Error(diagnostics, ErrorCode.WRN_UnobservedAwaitableExpression, expression.Syntax);
return;
}
// Then check if the method call returns a WinRT async type.
if (ImplementsWinRTAsyncInterface(call.Type))
{
Error(diagnostics, ErrorCode.WRN_UnobservedAwaitableExpression, expression.Syntax);
return;
}
// Finally, if we're in an async method, and the expression could be be awaited, report that it is instead discarded.
if (CouldBeAwaited(expression))
{
Error(diagnostics, ErrorCode.WRN_UnobservedAwaitableExpression, expression.Syntax);
}
}
开发者ID:elemk0vv,项目名称:roslyn-1,代码行数:51,代码来源:Binder_Statements.cs
示例14: RewriteEnumeratorForEachStatement
//.........这里部分代码省略.........
rewrittenBody: rewrittenBodyBlock,
breakLabel: node.BreakLabel,
continueLabel: node.ContinueLabel,
hasErrors: false);
BoundStatement result;
MethodSymbol disposeMethod;
if (enumeratorInfo.NeedsDisposeMethod && Binder.TryGetSpecialTypeMember(_compilation, SpecialMember.System_IDisposable__Dispose, forEachSyntax, _diagnostics, out disposeMethod))
{
Binder.ReportDiagnosticsIfObsolete(_diagnostics, disposeMethod, forEachSyntax,
hasBaseReceiver: false,
containingMember: _factory.CurrentMethod,
containingType: _factory.CurrentType,
location: enumeratorInfo.Location);
BoundBlock finallyBlockOpt;
var idisposableTypeSymbol = disposeMethod.ContainingType;
var conversions = new TypeConversions(_factory.CurrentMethod.ContainingAssembly.CorLibrary);
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
var isImplicit = conversions.ClassifyImplicitConversion(enumeratorType, idisposableTypeSymbol, ref useSiteDiagnostics).IsImplicit;
_diagnostics.Add(forEachSyntax, useSiteDiagnostics);
if (isImplicit)
{
Debug.Assert(enumeratorInfo.NeedsDisposeMethod);
Conversion receiverConversion = enumeratorType.IsStructType() ?
Conversion.Boxing :
Conversion.ImplicitReference;
// ((IDisposable)e).Dispose(); or e.Dispose();
BoundStatement disposeCall = new BoundExpressionStatement(forEachSyntax,
expression: SynthesizeCall(forEachSyntax, boundEnumeratorVar, disposeMethod, receiverConversion, idisposableTypeSymbol));
BoundStatement disposeStmt;
if (enumeratorType.IsValueType)
{
// No way for the struct to be nullable and disposable.
Debug.Assert(((TypeSymbol)enumeratorType.OriginalDefinition).SpecialType != SpecialType.System_Nullable_T);
// For non-nullable structs, no null check is required.
disposeStmt = disposeCall;
}
else
{
// NB: cast to object missing from spec. Needed to ignore user-defined operators and box type parameters.
// if ((object)e != null) ((IDisposable)e).Dispose();
disposeStmt = RewriteIfStatement(
syntax: forEachSyntax,
rewrittenCondition: new BoundBinaryOperator(forEachSyntax,
operatorKind: BinaryOperatorKind.NotEqual,
left: MakeConversion(
syntax: forEachSyntax,
rewrittenOperand: boundEnumeratorVar,
conversion: enumeratorInfo.EnumeratorConversion,
rewrittenType: _compilation.GetSpecialType(SpecialType.System_Object),
@checked: false),
right: MakeLiteral(forEachSyntax,
constantValue: ConstantValue.Null,
type: null),
constantValueOpt: null,
methodOpt: null,
resultKind: LookupResultKind.Viable,
type: _compilation.GetSpecialType(SpecialType.System_Boolean)),
开发者ID:CAPCHIK,项目名称:roslyn,代码行数:67,代码来源:LocalRewriter_ForEachStatement.cs
示例15: CreateBlockFromExpression
/// <summary>
/// Wrap a given expression e into a block as either { e; } or { return e; }
/// Shared between lambda and expression-bodied method binding.
/// </summary>
internal BoundBlock CreateBlockFromExpression(CSharpSyntaxNode node, ImmutableArray<LocalSymbol> locals, ExpressionSyntax expressionSyntax, BoundExpression expression, DiagnosticBag diagnostics)
{
var returnType = GetCurrentReturnType();
var syntax = expressionSyntax ?? expression.Syntax;
BoundStatement statement;
if ((object)returnType != null)
{
if (returnType.SpecialType == SpecialType.System_Void || IsTaskReturningAsyncMethod())
{
// If the return type is void then the expression is required to be a legal
// statement expression.
Debug.Assert(expressionSyntax != null || !IsValidStatementExpression(expression.Syntax, expression));
bool errors = false;
if (expressionSyntax == null || !IsValidStatementExpression(expressionSyntax, expression))
{
Error(diagnostics, ErrorCode.ERR_IllegalStatement, syntax);
errors = true;
}
// Don't mark compiler generated so that the rewriter generates sequence points
var expressionStatement = new BoundExpressionStatement(syntax, expression, errors);
CheckForUnobservedAwaitable(expressionStatement, diagnostics);
statement = expressionStatement;
}
else
{
expression = CreateReturnConversion(syntax, diagnostics, expression, returnType);
statement = new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true };
}
}
else if (expression.Type?.SpecialType == SpecialType.System_Void)
{
statement = new BoundExpressionStatement(syntax, expression) { WasCompilerGenerated = true };
}
else
{
statement = new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true };
}
// Need to attach the tree for when we generate sequence points.
return new BoundBlock(node, locals, ImmutableArray.Create(statement)) { WasCompilerGenerated = node.Kind() != SyntaxKind.ArrowExpressionClause };
}
开发者ID:elemk0vv,项目名称:roslyn-1,代码行数:50,代码来源:Binder_Statements.cs
示例16: VisitExpressionStatement
public override BoundNode VisitExpressionStatement(BoundExpressionStatement node)
{
BoundSpillSequence2 ss = null;
BoundExpression expr;
if (node.Expression.Kind == BoundKind.AwaitExpression)
{
// await expression with result discarded
var awaitExpression = (BoundAwaitExpression)node.Expression;
var expression = VisitExpression(ref ss, awaitExpression.Expression);
expr = awaitExpression.Update(expression, awaitExpression.GetAwaiter, awaitExpression.IsCompleted, awaitExpression.GetResult, awaitExpression.Type);
}
else
{
expr = VisitExpression(ref ss, node.Expression);
}
Debug.Assert(expr != null);
Debug.Assert(ss == null || ss.Value == null);
BoundStatement replacement = UpdateStatement(ss, node.Update(expr));
return replacement;
}
开发者ID:EkardNT,项目名称:Roslyn,代码行数:22,代码来源:AwaitLiftingRewriter.cs
示例17: RewriteUsingStatementTryFinally
private BoundStatement RewriteUsingStatementTryFinally(CSharpSyntaxNode syntax, BoundBlock tryBlock, BoundLocal local)
{
// SPEC: When ResourceType is a non-nullable value type, the expansion is:
// SPEC:
// SPEC: {
// SPEC: ResourceType resource = expr;
// SPEC: try { statement; }
// SPEC: finally { ((IDisposable)resource).Dispose(); }
// SPEC: }
// SPEC:
// SPEC: Otherwise, when Resource type is a nullable value type or
// SPEC: a reference type other than dynamic, the expansion is:
// SPEC:
// SPEC: {
// SPEC: ResourceType resource = expr;
// SPEC: try { statement; }
// SPEC: finally { if (resource != null) ((IDisposable)resource).Dispose(); }
// SPEC: }
// SPEC:
// SPEC: Otherwise, when ResourceType is dynamic, the expansion is:
// SPEC: {
// SPEC: dynamic resource = expr;
// SPEC: IDisposable d = (IDisposable)resource;
// SPEC: try { statement; }
// SPEC: finally { if (d != null) d.Dispose(); }
// SPEC: }
// SPEC:
// SPEC: An implementation is permitted to implement a given using statement
// SPEC: differently -- for example, for performance reasons -- as long as the
// SPEC: behavior is consistent with the above expansion.
//
// And we do in fact generate the code slightly differently than precisely how it is
// described above.
//
// First: if the type is a non-nullable value type then we do not do the
// *boxing conversion* from the resource to IDisposable. Rather, we do
// a *constrained virtual call* that elides the boxing if possible.
//
// Now, you might wonder if that is legal; isn't skipping the boxing producing
// an observable difference? Because if the value type is mutable and the Dispose
// mutates it, then skipping the boxing means that we are now mutating the original,
// not the boxed copy. But this is never observable. Either (1) we have "using(R r = x){}"
// and r is out of scope after the finally, so it is not possible to observe the mutation,
// or (2) we have "using(x) {}". But that has the semantics of "using(R temp = x){}",
// so again, we are not mutating x to begin with; we're always mutating a copy. Therefore
// it doesn't matter if we skip making *a copy of the copy*.
//
// This is what the dev10 compiler does, and we do so as well.
//
// Second: if the type is a nullable value type then we can similarly elide the boxing.
// We can generate
//
// {
// ResourceType resource = expr;
// try { statement; }
// finally { if (resource.HasValue) resource.GetValueOrDefault().Dispose(); }
// }
//
// Where again we do a constrained virtual call to Dispose, rather than boxing
// the value to IDisposable.
//
// Note that this optimization is *not* what the native compiler does; in this case
// the native compiler behavior is to test for HasValue, then *box* and convert
// the boxed value to IDisposable. There's no need to do that.
//
// Third: if we have "using(x)" and x is dynamic then obviously we need not generate
// "{ dynamic temp1 = x; IDisposable temp2 = (IDisposable) temp1; ... }". Rather, we elide
// the completely unnecessary first temporary.
BoundExpression disposedExpression;
bool isNullableValueType = local.Type.IsNullableType();
if (isNullableValueType)
{
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, local.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
// local.GetValueOrDefault()
disposedExpression = BoundCall.Synthesized(syntax, local, getValueOrDefault);
}
else
{
// local
disposedExpression = local;
}
// local.Dispose()
BoundExpression disposeCall;
MethodSymbol disposeMethodSymbol;
if (TryGetSpecialTypeMember(syntax, SpecialMember.System_IDisposable__Dispose, out disposeMethodSymbol))
{
disposeCall = BoundCall.Synthesized(syntax, disposedExpression, disposeMethodSymbol);
}
else
{
disposeCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray<Symbol>.Empty, ImmutableArray.Create<BoundNode>(disposedExpression), ErrorTypeSymbol.UnknownResultType);
}
// local.Dispose();
BoundStatement disposeStatement = new BoundExpressionStatement(syntax, disposeCall);
//.........这里部分代码省略.........
开发者ID:EkardNT,项目名称:Roslyn,代码行数:101,代码来源:LocalRewriter_UsingStatement.cs
示例18: VisitExpressionStatement
public override BoundNode VisitExpressionStatement(BoundExpressionStatement node)
{
if (node.Expression.Kind == BoundKind.AwaitExpression)
{
var awaitExpression = VisitAwaitExpression((BoundAwaitExpression)node.Expression, resultsDiscarded: true);
return node.Update(awaitExpression);
}
return base.VisitExpressionStatement(node);
}
开发者ID:EkardNT,项目名称:Roslyn,代码行数:10,代码来源:AsyncMethodToClassRewriter.cs
示例19: InstrumentExpressionStatement
public override BoundStatement InstrumentExpressionStatement(BoundExpressionStatement original, BoundStatement rewritten)
{
return Previous.InstrumentExpressionStatement(original, rewritten);
}
开发者ID:tvsonar,项目名称:roslyn,代码行数:4,代码来源:CompoundInstrumenter.cs
示例20: BindGlobalStatement
private static BoundInitializer BindGlobalStatement(
Binder binder,
SynthesizedInteractiveInitializerMethod scriptInitializer,
StatementSyntax statementNode,
DiagnosticBag diagnostics,
bool isLast)
{
var statement = binder.BindStatement(statementNode, diagnostics);
if (isLast && !statement.HasAnyErrors)
{
// the result of the last global expression is assigned to the result storage for submission result:
if (binder.Compilation.IsSubmission)
{
// insert an implicit conversion for the submission return type (if needed):
var expression = InitializerRewriter.GetTrailingScriptExpression(statement);
if (expression != null &&
((object)expression.Type == null || expression.Type.SpecialType != SpecialType.System_Void))
{
var submissionResultType = scriptInitializer.ResultType;
expression = binder.GenerateConversionForAssignment(submissionResultType, expression, diagnostics);
statement = new BoundExpressionStatement(statement.Syntax, expression, expression.HasErrors);
}
}
// don't allow trailing expressions after labels (as in regular C#, labels must be followed by a statement):
if (statement.Kind == BoundKind.LabeledStatement)
{
var labeledStatementBody = ((BoundLabeledStatement)statement).Body;
while (labeledStatementBody.Kind == BoundKind.LabeledStatement)
{
labeledStatementBody = ((BoundLabeledStatement)labeledStatementBody).Body;
}
if (InitializerRewriter.GetTrailingScriptExpression(labeledStatementBody) != null)
{
Error(diagnostics, ErrorCode.ERR_SemicolonExpected, ((ExpressionStatementSyntax)labeledStatementBody.Syntax).SemicolonToken);
}
}
}
return new BoundGlobalStatementInitializer(statementNode, statement);
}
|
请发表评论