本文整理汇总了C#中Microsoft.CodeAnalysis.CSharp.BoundDefaultOperator类的典型用法代码示例。如果您正苦于以下问题:C# BoundDefaultOperator类的具体用法?C# BoundDefaultOperator怎么用?C# BoundDefaultOperator使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
BoundDefaultOperator类属于Microsoft.CodeAnalysis.CSharp命名空间,在下文中一共展示了BoundDefaultOperator类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: Rewrite
/// <summary>
/// The flow analysis pass. This pass reports required diagnostics for unreachable
/// statements and uninitialized variables (through the call to FlowAnalysisWalker.Analyze),
/// and inserts a final return statement if the end of a void-returning method is reachable.
/// </summary>
/// <param name="method">the method to be analyzed</param>
/// <param name="block">the method's body</param>
/// <param name="diagnostics">the receiver of the reported diagnostics</param>
/// <param name="hasTrailingExpression">indicates whether this Script had a trailing expression</param>
/// <param name="originalBodyNested">the original method body is the last statement in the block</param>
/// <returns>the rewritten block for the method (with a return statement possibly inserted)</returns>
public static BoundBlock Rewrite(
MethodSymbol method,
BoundBlock block,
DiagnosticBag diagnostics,
bool hasTrailingExpression,
bool originalBodyNested)
{
#if DEBUG
// We should only see a trailingExpression if we're in a Script initializer.
Debug.Assert(!hasTrailingExpression || method.IsScriptInitializer);
var initialDiagnosticCount = diagnostics.ToReadOnly().Length;
#endif
var compilation = method.DeclaringCompilation;
if (method.ReturnsVoid || method.IsIterator ||
(method.IsAsync && compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task) == method.ReturnType))
{
// we don't analyze synthesized void methods.
if ((method.IsImplicitlyDeclared && !method.IsScriptInitializer) || Analyze(compilation, method, block, diagnostics))
{
block = AppendImplicitReturn(block, method, (CSharpSyntaxNode)(method as SourceMethodSymbol)?.BodySyntax, originalBodyNested);
}
}
else if (Analyze(compilation, method, block, diagnostics))
{
// If the method is a lambda expression being converted to a non-void delegate type
// and the end point is reachable then suppress the error here; a special error
// will be reported by the lambda binder.
Debug.Assert(method.MethodKind != MethodKind.AnonymousFunction);
// Add implicit "return default(T)" if this is a submission that does not have a trailing expression.
var submissionResultType = (method as SynthesizedInteractiveInitializerMethod)?.ResultType;
if (!hasTrailingExpression && ((object)submissionResultType != null))
{
Debug.Assert(submissionResultType.SpecialType != SpecialType.System_Void);
var trailingExpression = new BoundDefaultOperator(method.GetNonNullSyntaxNode(), submissionResultType);
var newStatements = block.Statements.Add(new BoundReturnStatement(trailingExpression.Syntax, trailingExpression));
block = new BoundBlock(block.Syntax, ImmutableArray<LocalSymbol>.Empty, newStatements) { WasCompilerGenerated = true };
#if DEBUG
// It should not be necessary to repeat analysis after adding this node, because adding a trailing
// return in cases where one was missing should never produce different Diagnostics.
var flowAnalysisDiagnostics = DiagnosticBag.GetInstance();
Debug.Assert(!Analyze(compilation, method, block, flowAnalysisDiagnostics));
Debug.Assert(flowAnalysisDiagnostics.ToReadOnly().SequenceEqual(diagnostics.ToReadOnly().Skip(initialDiagnosticCount)));
flowAnalysisDiagnostics.Free();
#endif
}
// If there's more than one location, then the method is partial and we
// have already reported a non-void partial method error.
else if (method.Locations.Length == 1)
{
diagnostics.Add(ErrorCode.ERR_ReturnExpected, method.Locations[0], method);
}
}
return block;
}
示例2: RewriteScriptInitializer
internal static BoundTypeOrInstanceInitializers RewriteScriptInitializer(ImmutableArray<BoundInitializer> boundInitializers, SynthesizedInteractiveInitializerMethod method)
{
Debug.Assert(!boundInitializers.IsDefault);
var boundStatements = ArrayBuilder<BoundStatement>.GetInstance(boundInitializers.Length);
var submissionResultType = method.ResultType;
BoundExpression submissionResult = null;
foreach (var initializer in boundInitializers)
{
// The value of the last expression statement (if any) is returned from the submission initializer.
if (((object)submissionResultType != null) &&
(initializer == boundInitializers.Last()) &&
(initializer.Kind == BoundKind.GlobalStatementInitializer))
{
var statement = ((BoundGlobalStatementInitializer)initializer).Statement;
if (statement.Kind == BoundKind.ExpressionStatement)
{
var expr = ((BoundExpressionStatement)statement).Expression;
if ((object)expr.Type != null && expr.Type.SpecialType != SpecialType.System_Void)
{
submissionResult = expr;
continue;
}
}
}
boundStatements.Add(RewriteInitializersAsStatements(initializer));
}
var syntax = method.GetNonNullSyntaxNode();
if ((object)submissionResultType != null)
{
if (submissionResult == null)
{
// Return default(T) if submission does not have a trailing expression.
submissionResult = new BoundDefaultOperator(syntax, submissionResultType);
}
Debug.Assert(submissionResult.Type.SpecialType != SpecialType.System_Void);
// The expression is converted to the submission result type when the initializer is bound.
boundStatements.Add(new BoundReturnStatement(submissionResult.Syntax, submissionResult));
}
return new BoundTypeOrInstanceInitializers(syntax, boundStatements.ToImmutableAndFree());
}
示例3: OptimizeLiftedBooleanOperatorOneNull
private BoundExpression OptimizeLiftedBooleanOperatorOneNull(
CSharpSyntaxNode syntax,
BinaryOperatorKind kind,
BoundExpression left,
BoundExpression right)
{
// Here we optimize the cases where one side is known to be null.
bool leftAlwaysNull = NullableNeverHasValue(left);
bool rightAlwaysNull = NullableNeverHasValue(right);
Debug.Assert(!(leftAlwaysNull && rightAlwaysNull)); // We've already optimized this case.
if (!(leftAlwaysNull || rightAlwaysNull))
{
return null;
}
// First, if one operand is null and the other is definitely non null, then we can eliminate
// all the temporaries:
//
// new bool?() & new bool?(B())
// new bool?() | new bool?(B())
//
// can be generated as
//
// B() ? new bool?() : new bool?(false)
// B() ? new bool?(true) : new bool?()
//
// respectively.
BoundExpression alwaysNull = leftAlwaysNull ? left : right;
BoundExpression notAlwaysNull = leftAlwaysNull ? right : left;
BoundExpression neverNull = NullableAlwaysHasValue(notAlwaysNull);
BoundExpression nullBool = new BoundDefaultOperator(syntax, null, alwaysNull.Type);
if (neverNull != null)
{
BoundExpression newNullBool = MakeNewNullableBoolean(syntax, kind == BinaryOperatorKind.LiftedBoolOr);
return RewriteConditionalOperator(
syntax: syntax,
rewrittenCondition: neverNull,
rewrittenConsequence: kind == BinaryOperatorKind.LiftedBoolAnd ? nullBool : newNullBool,
rewrittenAlternative: kind == BinaryOperatorKind.LiftedBoolAnd ? newNullBool : nullBool,
constantValueOpt: null,
rewrittenType: alwaysNull.Type);
}
// Now we optimize the case where one operand is null and the other is not. We generate
//
// new bool?() & M()
// new bool?() | M()
//
// as
//
// bool? t = M(), t.GetValueOrDefault() ? new bool?() : t
// bool? t = M(), t.GetValueOrDefault() ? t : new bool?()
//
// respectively.
BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp = _factory.StoreToTemp(notAlwaysNull, out tempAssignment);
BoundExpression condition = MakeOptimizedGetValueOrDefault(syntax, boundTemp);
BoundExpression consequence = kind == BinaryOperatorKind.LiftedBoolAnd ? nullBool : boundTemp;
BoundExpression alternative = kind == BinaryOperatorKind.LiftedBoolAnd ? boundTemp : nullBool;
BoundExpression conditionalExpression = RewriteConditionalOperator(
syntax: syntax,
rewrittenCondition: condition,
rewrittenConsequence: consequence,
rewrittenAlternative: alternative,
constantValueOpt: null,
rewrittenType: alwaysNull.Type);
return new BoundSequence(
syntax: syntax,
locals: ImmutableArray.Create<LocalSymbol>(boundTemp.LocalSymbol),
sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignment),
value: conditionalExpression,
type: conditionalExpression.Type);
}
示例4: LowerLiftedBinaryArithmeticOperator
private BoundExpression LowerLiftedBinaryArithmeticOperator(
CSharpSyntaxNode syntax,
BinaryOperatorKind kind,
BoundExpression loweredLeft,
BoundExpression loweredRight,
TypeSymbol type,
MethodSymbol method)
{
// We have a lifted * / % + - << >> ^ & | binary operator. We begin with trivial
// optimizations; if both sides are null or neither side is null then we can
// eliminate the lifting altogether.
BoundExpression optimized = OptimizeLiftedBinaryArithmetic(syntax, kind, loweredLeft, loweredRight, type, method);
if (optimized != null)
{
return optimized;
}
// We now know that neither side is null. However, we might have an operand that is known
// to be non-null. If neither side is known to be non-null then we generate:
//
// S? tempX = left;
// S? tempY = right;
// R? r = tempX.HasValue & tempY.HasValue ?
// new R?(tempX.GetValueOrDefault() OP tempY.GetValueOrDefault()) :
// default(R?);
//
// If one of the operands, say the right, is non-null, then we generate:
//
// S? tempX = left;
// S tempY = right; // not null
// R? r = tempX.HasValue ?
// new R?(tempX.GetValueOrDefault() OP tempY) :
// default(R?);
//
var sideeffects = ArrayBuilder<BoundExpression>.GetInstance();
var locals = ArrayBuilder<LocalSymbol>.GetInstance();
BoundExpression leftNeverNull = NullableAlwaysHasValue(loweredLeft);
BoundExpression rightNeverNull = NullableAlwaysHasValue(loweredRight);
BoundExpression boundTempX = leftNeverNull ?? loweredLeft;
boundTempX = CaptureNullableOperandInTempIfNeeded(boundTempX, sideeffects, locals);
BoundExpression boundTempY = rightNeverNull ?? loweredRight;
boundTempY = CaptureNullableOperandInTempIfNeeded(boundTempY, sideeffects, locals);
BoundExpression callX_GetValueOrDefault = MakeOptimizedGetValueOrDefault(syntax, boundTempX);
BoundExpression callY_GetValueOrDefault = MakeOptimizedGetValueOrDefault(syntax, boundTempY);
BoundExpression callX_HasValue = MakeOptimizedHasValue(syntax, boundTempX);
BoundExpression callY_HasValue = MakeOptimizedHasValue(syntax, boundTempY);
// tempX.HasValue & tempY.HasValue
TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);
BoundExpression condition = MakeBinaryOperator(syntax, BinaryOperatorKind.BoolAnd, callX_HasValue, callY_HasValue, boolType, null);
// new R?(tempX.GetValueOrDefault() OP tempY.GetValueOrDefault)
BoundExpression consequence = MakeLiftedBinaryOperatorConsequence(syntax, kind, callX_GetValueOrDefault, callY_GetValueOrDefault, type, method);
// default(R?)
BoundExpression alternative = new BoundDefaultOperator(syntax, null, type);
// tempX.HasValue & tempY.HasValue ?
// new R?(tempX.GetValueOrDefault() OP tempY.GetValueOrDefault()) :
// default(R?);
BoundExpression conditionalExpression = RewriteConditionalOperator(
syntax: syntax,
rewrittenCondition: condition,
rewrittenConsequence: consequence,
rewrittenAlternative: alternative,
constantValueOpt: null,
rewrittenType: type);
return new BoundSequence(
syntax: syntax,
locals: locals.ToImmutableAndFree(),
sideEffects: sideeffects.ToImmutableAndFree(),
value: conditionalExpression,
type: type);
}
示例5: MakeLiftedDecimalIncDecOperator
private BoundExpression MakeLiftedDecimalIncDecOperator(CSharpSyntaxNode syntax, BinaryOperatorKind oper, BoundExpression operand)
{
Debug.Assert(operand.Type.IsNullableType() && operand.Type.GetNullableUnderlyingType().SpecialType == SpecialType.System_Decimal);
// This method assumes that operand is already a temporary and so there is no need to copy it again.
MethodSymbol method = GetDecimalIncDecOperator(oper);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol ctor = GetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T__ctor);
// x.HasValue
BoundExpression condition = MakeNullableHasValue(syntax, operand);
// x.GetValueOrDefault()
BoundExpression getValueCall = BoundCall.Synthesized(syntax, operand, getValueOrDefault);
// op_Inc(x.GetValueOrDefault())
BoundExpression methodCall = BoundCall.Synthesized(syntax, null, method, getValueCall);
// new decimal?(op_Inc(x.GetValueOrDefault()))
BoundExpression consequence = new BoundObjectCreationExpression(syntax, ctor, methodCall);
// default(decimal?)
BoundExpression alternative = new BoundDefaultOperator(syntax, null, operand.Type);
// x.HasValue ? new decimal?(op_Inc(x.GetValueOrDefault())) : default(decimal?)
return RewriteConditionalOperator(syntax, condition, consequence, alternative, ConstantValue.NotAvailable, operand.Type);
}
示例6: MakeUserDefinedIncrementOperator
private BoundExpression MakeUserDefinedIncrementOperator(BoundIncrementOperator node, BoundExpression rewrittenValueToIncrement)
{
Debug.Assert((object)node.MethodOpt != null);
Debug.Assert(node.MethodOpt.ParameterCount == 1);
bool isLifted = node.OperatorKind.IsLifted();
bool @checked = node.OperatorKind.IsChecked();
BoundExpression rewrittenArgument = rewrittenValueToIncrement;
CSharpSyntaxNode syntax = node.Syntax;
TypeSymbol type = node.MethodOpt.ParameterTypes[0];
if (isLifted)
{
type = _compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(type);
Debug.Assert(node.MethodOpt.ParameterTypes[0] == node.MethodOpt.ReturnType);
}
if (!node.OperandConversion.IsIdentity)
{
rewrittenArgument = MakeConversionNode(
syntax: syntax,
rewrittenOperand: rewrittenValueToIncrement,
conversion: node.OperandConversion,
rewrittenType: type,
@checked: @checked);
}
if (!isLifted)
{
return BoundCall.Synthesized(syntax, null, node.MethodOpt, rewrittenArgument);
}
// S? temp = operand;
// S? r = temp.HasValue ?
// new S?(op_Increment(temp.GetValueOrDefault())) :
// default(S?);
// Unlike the other unary operators, we do not attempt to optimize nullable user-defined
// increment or decrement. The operand is a variable (or property), and so we do not know if
// it is always null/never null.
BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp = _factory.StoreToTemp(rewrittenArgument, out tempAssignment);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol ctor = GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);
// temp.HasValue
BoundExpression condition = MakeNullableHasValue(node.Syntax, boundTemp);
// temp.GetValueOrDefault()
BoundExpression call_GetValueOrDefault = BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault);
// op_Increment(temp.GetValueOrDefault())
BoundExpression userDefinedCall = BoundCall.Synthesized(syntax, null, node.MethodOpt, call_GetValueOrDefault);
// new S?(op_Increment(temp.GetValueOrDefault()))
BoundExpression consequence = new BoundObjectCreationExpression(syntax, ctor, userDefinedCall);
// default(S?)
BoundExpression alternative = new BoundDefaultOperator(syntax, null, type);
// temp.HasValue ?
// new S?(op_Increment(temp.GetValueOrDefault())) :
// default(S?);
BoundExpression conditionalExpression = RewriteConditionalOperator(
syntax: syntax,
rewrittenCondition: condition,
rewrittenConsequence: consequence,
rewrittenAlternative: alternative,
constantValueOpt: null,
rewrittenType: type);
// temp = operand;
// temp.HasValue ?
// new S?(op_Increment(temp.GetValueOrDefault())) :
// default(S?);
return new BoundSequence(
syntax: syntax,
locals: ImmutableArray.Create<LocalSymbol>(boundTemp.LocalSymbol),
sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignment),
value: conditionalExpression,
type: type);
}
示例7: LowerLiftedUnaryOperator
private BoundExpression LowerLiftedUnaryOperator(
UnaryOperatorKind kind,
CSharpSyntaxNode syntax,
MethodSymbol method,
BoundExpression loweredOperand,
TypeSymbol type)
{
// First, an optimization. If we know that the operand is always null then
// we can simply lower to the alternative.
BoundExpression optimized = OptimizeLiftedUnaryOperator(kind, syntax, method, loweredOperand, type);
if (optimized != null)
{
return optimized;
}
// We do not know whether the operand is null or non-null, so we generate:
//
// S? temp = operand;
// R? r = temp.HasValue ?
// new R?(OP(temp.GetValueOrDefault())) :
// default(R?);
BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp = _factory.StoreToTemp(loweredOperand, out tempAssignment);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
// temp.HasValue
BoundExpression condition = MakeNullableHasValue(syntax, boundTemp);
// temp.GetValueOrDefault()
BoundExpression call_GetValueOrDefault = BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault);
// new R?(temp.GetValueOrDefault())
BoundExpression consequence = GetLiftedUnaryOperatorConsequence(kind, syntax, method, type, call_GetValueOrDefault);
// default(R?)
BoundExpression alternative = new BoundDefaultOperator(syntax, null, type);
// temp.HasValue ?
// new R?(OP(temp.GetValueOrDefault())) :
// default(R?);
BoundExpression conditionalExpression = RewriteConditionalOperator(
syntax: syntax,
rewrittenCondition: condition,
rewrittenConsequence: consequence,
rewrittenAlternative: alternative,
constantValueOpt: null,
rewrittenType: type);
// temp = operand;
// temp.HasValue ?
// new R?(OP(temp.GetValueOrDefault())) :
// default(R?);
return new BoundSequence(
syntax: syntax,
locals: ImmutableArray.Create<LocalSymbol>(boundTemp.LocalSymbol),
sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignment),
value: conditionalExpression,
type: type);
}
示例8: BindReturn
private BoundReturnStatement BindReturn(ReturnStatementSyntax syntax, DiagnosticBag diagnostics)
{
var expressionSyntax = syntax.Expression;
BoundExpression arg = null;
if (expressionSyntax != null)
{
arg = BindValue(expressionSyntax, diagnostics, BindValueKind.RValue);
}
else
{
// If this is a void return statement in a script, return default(T).
var interactiveInitializerMethod = this.ContainingMemberOrLambda as SynthesizedInteractiveInitializerMethod;
if (interactiveInitializerMethod != null)
{
arg = new BoundDefaultOperator(interactiveInitializerMethod.GetNonNullSyntaxNode(), interactiveInitializerMethod.ResultType);
}
}
bool hasErrors;
if (IsDirectlyInIterator)
{
diagnostics.Add(ErrorCode.ERR_ReturnInIterator, syntax.ReturnKeyword.GetLocation());
hasErrors = true;
}
else if (arg != null)
{
hasErrors = arg.HasErrors || ((object)arg.Type != null && arg.Type.IsErrorType());
}
else
{
hasErrors = false;
}
if (hasErrors)
{
return new BoundReturnStatement(syntax, arg, hasErrors: true);
}
TypeSymbol retType = GetCurrentReturnType();
// The return type could be null; we might be attempting to infer the return type either
// because of method type inference, or because we are attempting to do error analysis
// on a lambda expression of unknown return type.
if ((object)retType != null)
{
if (retType.SpecialType == SpecialType.System_Void || IsTaskReturningAsyncMethod())
{
if (arg != null)
{
var container = this.ContainingMemberOrLambda;
var lambda = container as LambdaSymbol;
if ((object)lambda != null)
{
// Error case: void-returning or async task-returning method or lambda with "return x;"
var errorCode = retType.SpecialType == SpecialType.System_Void
? ErrorCode.ERR_RetNoObjectRequiredLambda
: ErrorCode.ERR_TaskRetNoObjectRequiredLambda;
// Anonymous function converted to a void returning delegate cannot return a value
Error(diagnostics, errorCode, syntax.ReturnKeyword);
// COMPATIBILITY: The native compiler also produced an error
// COMPATIBILITY: "Cannot convert lambda expression to delegate type 'Action' because some of the
// COMPATIBILITY: return types in the block are not implicitly convertible to the delegate return type"
// COMPATIBILITY: This error doesn't make sense in the "void" case because the whole idea of
// COMPATIBILITY: "conversion to void" is a bit unusual, and we've already given a good error.
}
else
{
// Error case: void-returning or async task-returning method or lambda with "return x;"
var errorCode = retType.SpecialType == SpecialType.System_Void
? ErrorCode.ERR_RetNoObjectRequired
: ErrorCode.ERR_TaskRetNoObjectRequired;
Error(diagnostics, errorCode, syntax.ReturnKeyword, container);
}
}
}
else
{
if (arg == null)
{
// Error case: non-void-returning or Task<T>-returning method or lambda but just have "return;"
var requiredType = IsGenericTaskReturningAsyncMethod()
? retType.GetMemberTypeArgumentsNoUseSiteDiagnostics().Single()
: retType;
Error(diagnostics, ErrorCode.ERR_RetObjectRequired, syntax.ReturnKeyword, requiredType);
}
else
{
arg = CreateReturnConversion(syntax, diagnostics, arg, retType);
}
}
}
else
{
// Check that the returned expression is not void.
if ((object)arg?.Type != null && arg.Type.SpecialType == SpecialType.System_Void)
{
//.........这里部分代码省略.........
示例9: RewriteLiftedUserDefinedConversion
private BoundExpression RewriteLiftedUserDefinedConversion(
CSharpSyntaxNode syntax,
BoundExpression rewrittenOperand,
MethodSymbol method,
TypeSymbol rewrittenType,
ConversionKind conversionKind)
{
if (inExpressionLambda)
{
Conversion conv = MakeConversion(syntax, new Conversion(conversionKind, method, false), rewrittenOperand.Type, rewrittenType);
return BoundConversion.Synthesized(syntax, rewrittenOperand, conv, false, true, default(ConstantValue), rewrittenType);
}
// DELIBERATE SPEC VIOLATION:
// The native compiler allows for a "lifted" conversion even when the return type of the conversion
// not a non-nullable value type. For example, if we have a conversion from struct S to string,
// then a "lifted" conversion from S? to string is considered by the native compiler to exist,
// with the semantics of "s.HasValue ? (string)s.Value : (string)null". The Roslyn compiler
// perpetuates this error for the sake of backwards compatibility.
Debug.Assert((object)rewrittenType != null);
Debug.Assert(rewrittenOperand.Type.IsNullableType());
BoundExpression optimized = OptimizeLiftedUserDefinedConversion(syntax, rewrittenOperand, conversionKind, method, rewrittenType);
if (optimized != null)
{
return optimized;
}
// We have no optimizations we can perform. If the return type of the
// conversion method is a non-nullable value type R then we lower this as:
//
// temp = operand
// temp.HasValue ? new R?(op_Whatever(temp.GetValueOrDefault())) : default(R?)
//
// Otherwise, if the return type of the conversion is a nullable value type, reference type
// or pointer type P, then we lower this as:
//
// temp = operand
// temp.HasValue ? op_Whatever(temp.GetValueOrDefault()) : default(P)
BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp = factory.StoreToTemp(rewrittenOperand, out tempAssignment);
MethodSymbol get_HasValue = GetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_get_HasValue);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
// temp.HasValue
BoundExpression condition = BoundCall.Synthesized(syntax, boundTemp, get_HasValue);
// temp.GetValueOrDefault()
BoundCall callGetValueOrDefault = BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault);
// op_Whatever(temp.GetValueOrDefault())
BoundCall userDefinedCall = BoundCall.Synthesized(syntax, null, method, callGetValueOrDefault);
// new R?(op_Whatever(temp.GetValueOrDefault())
BoundExpression consequence = MakeLiftedUserDefinedConversionConsequence(userDefinedCall, rewrittenType);
// default(R?)
BoundExpression alternative = new BoundDefaultOperator(syntax, rewrittenType);
// temp.HasValue ? new R?(op_Whatever(temp.GetValueOrDefault())) : default(R?)
BoundExpression conditionalExpression = RewriteConditionalOperator(
syntax: syntax,
rewrittenCondition: condition,
rewrittenConsequence: consequence,
rewrittenAlternative: alternative,
constantValueOpt: null,
rewrittenType: rewrittenType);
// temp = operand
// temp.HasValue ? new R?(op_Whatever(temp.GetValueOrDefault())) : default(R?)
return new BoundSequence(
syntax: syntax,
locals: ImmutableArray.Create(boundTemp.LocalSymbol),
sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignment),
value: conditionalExpression,
type: rewrittenType);
}
示例10: RewriteFullyLiftedBuiltInConversion
private BoundExpression RewriteFullyLiftedBuiltInConversion(
CSharpSyntaxNode syntax,
BoundExpression operand,
ConversionKind kind,
bool @checked,
TypeSymbol type)
{
// SPEC: If the nullable conversion is from S? to T?:
// SPEC: * If the source HasValue property is false the result
// SPEC: is a null value of type T?.
// SPEC: * Otherwise the conversion is evaluated as an unwrapping
// SPEC: from S? to S, followed by the underlying conversion from
// SPEC: S to T, followed by a wrapping from T to T?
BoundExpression optimized = OptimizeLiftedBuiltInConversion(syntax, operand, kind, @checked, type);
if (optimized != null)
{
return optimized;
}
// We are unable to optimize the conversion. "(T?)s" is generated as:
// S? temp = s;
// temp.HasValue ? new T?((T)temp.GetValueOrDefault()) : default(T?)
BoundAssignmentOperator tempAssignment;
var boundTemp = factory.StoreToTemp(operand, out tempAssignment);
MethodSymbol get_HasValue = GetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_get_HasValue);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
BoundExpression condition = BoundCall.Synthesized(syntax, boundTemp, get_HasValue);
BoundExpression consequence = new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor),
MakeConversion(
BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault),
type.GetNullableUnderlyingType(),
@checked));
BoundExpression alternative = new BoundDefaultOperator(syntax, null, type);
BoundExpression conditionalExpression = RewriteConditionalOperator(
syntax: syntax,
rewrittenCondition: condition,
rewrittenConsequence: consequence,
rewrittenAlternative: alternative,
constantValueOpt: null,
rewrittenType: type);
return new BoundSequence(
syntax: syntax,
locals: ImmutableArray.Create(boundTemp.LocalSymbol),
sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignment),
value: conditionalExpression,
type: type);
}
示例11: GetDefaultParameterValue
//.........这里部分代码省略.........
BaseFieldDeclarationSyntax fieldDecl;
if (memberDecl.Kind() == SyntaxKind.PropertyDeclaration)
{
var propDecl = (PropertyDeclarationSyntax)memberDecl;
EqualsValueClauseSyntax initializer = propDecl.Initializer;
if (initializer != null && initializer.Span.Contains(syntax.Span))
{
memberName = propDecl.Identifier.ValueText;
break;
}
}
else if ((fieldDecl = memberDecl as BaseFieldDeclarationSyntax) != null)
{
memberName = null;
foreach (VariableDeclaratorSyntax varDecl in fieldDecl.Declaration.Variables)
{
EqualsValueClauseSyntax initializer = varDecl.Initializer;
if (initializer != null && initializer.Span.Contains(syntax.Span))
{
memberName = varDecl.Identifier.ValueText;
break;
}
}
if (memberName != null)
{
break;
}
}
}
goto default;
default:
memberName = _factory.TopLevelMethod.GetMemberCallerName();
break;
}
BoundExpression memberNameLiteral = MakeLiteral(syntax, ConstantValue.Create(memberName), _compilation.GetSpecialType(SpecialType.System_String));
defaultValue = MakeConversionNode(memberNameLiteral, parameterType, false);
}
else if (defaultConstantValue == ConstantValue.NotAvailable)
{
// There is no constant value given for the parameter in source/metadata.
if (parameterType.IsDynamic() || parameterType.SpecialType == SpecialType.System_Object)
{
// We have something like M([Optional] object x). We have special handling for such situations.
defaultValue = GetDefaultParameterSpecial(syntax, parameter);
}
else
{
// The argument to M([Optional] int x) becomes default(int)
defaultValue = new BoundDefaultOperator(syntax, parameterType);
}
}
else if (defaultConstantValue.IsNull && parameterType.IsValueType)
{
// We have something like M(int? x = null) or M(S x = default(S)),
// so replace the argument with default(int?).
defaultValue = new BoundDefaultOperator(syntax, parameterType);
}
else if (parameterType.IsNullableType())
{
// We have something like M(double? x = 1.23), so replace the argument
// with new double?(1.23).
TypeSymbol constantType = _compilation.GetSpecialType(defaultConstantValue.SpecialType);
defaultValue = MakeLiteral(syntax, defaultConstantValue, constantType);
// The parameter's underlying type might not match the constant type. For example, we might have
// a default value of 5 (an integer) but a parameter type of decimal?.
defaultValue = MakeConversionNode(defaultValue, parameterType.GetNullableUnderlyingType(), @checked: false, acceptFailingConversion: true);
// Finally, wrap it in a nullable ctor.
defaultValue = new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor),
defaultValue);
}
else if (defaultConstantValue.IsNull || defaultConstantValue.IsBad)
{
defaultValue = MakeLiteral(syntax, defaultConstantValue, parameterType);
}
else
{
// We have something like M(double x = 1.23), so replace the argument with 1.23.
TypeSymbol constantType = _compilation.GetSpecialType(defaultConstantValue.SpecialType);
defaultValue = MakeLiteral(syntax, defaultConstantValue, constantType);
// The parameter type might not match the constant type.
defaultValue = MakeConversionNode(defaultValue, parameterType, @checked: false, acceptFailingConversion: true);
}
return defaultValue;
}
示例12: GetDefaultParameterSpecial
private BoundExpression GetDefaultParameterSpecial(SyntaxNode syntax, ParameterSymbol parameter)
{
// We have a call to a method M([Optional] object x) which omits the argument. The value we generate
// for the argument depends on the presence or absence of other attributes. The rules are:
//
// * If the parameter is marked as [MarshalAs(Interface)], [MarshalAs(IUnknown)] or [MarshalAs(IDispatch)]
// then the argument is null.
// * Otherwise, if the parameter is marked as [IUnknownConstant] then the argument is
// new UnknownWrapper(null)
// * Otherwise, if the parameter is marked as [IDispatchConstant] then the argument is
// new DispatchWrapper(null)
// * Otherwise, the argument is Type.Missing.
BoundExpression defaultValue;
if (parameter.IsMarshalAsObject)
{
// default(object)
defaultValue = new BoundDefaultOperator(syntax, parameter.Type);
}
else if (parameter.IsIUnknownConstant)
{
// new UnknownWrapper(default(object))
var methodSymbol = (MethodSymbol)_compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_InteropServices_UnknownWrapper__ctor);
var argument = new BoundDefaultOperator(syntax, parameter.Type);
defaultValue = new BoundObjectCreationExpression(syntax, methodSymbol, argument);
}
else if (parameter.IsIDispatchConstant)
{
// new DispatchWrapper(default(object))
var methodSymbol = (MethodSymbol)_compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_InteropServices_DispatchWrapper__ctor);
var argument = new BoundDefaultOperator(syntax, parameter.Type);
defaultValue = new BoundObjectCreationExpression(syntax, methodSymbol, argument);
}
else
{
// Type.Missing
var fieldSymbol = (FieldSymbol)_compilation.GetWellKnownTypeMember(WellKnownMember.System_Type__Missing);
defaultValue = new BoundFieldAccess(syntax, null, fieldSymbol, ConstantValue.NotAvailable);
}
defaultValue = MakeConversionNode(defaultValue, parameter.Type, @checked: false);
return defaultValue;
}
示例13: VisitObjectCreationExpression
public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
{
Debug.Assert(node != null);
// Rewrite the arguments.
// NOTE: We may need additional argument rewriting such as generating a params array,
// re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
// NOTE: This is done later by MakeArguments, for now we just lower each argument.
var rewrittenArguments = VisitList(node.Arguments);
// We have already lowered each argument, but we may need some additional rewriting for the arguments,
// such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
ImmutableArray<LocalSymbol> temps;
ImmutableArray<RefKind> argumentRefKindsOpt = node.ArgumentRefKindsOpt;
rewrittenArguments = MakeArguments(node.Syntax, rewrittenArguments, node.Constructor, node.Constructor, node.Expanded, node.ArgsToParamsOpt, ref argumentRefKindsOpt, out temps);
BoundExpression rewrittenObjectCreation;
if (_inExpressionLambda)
{
if (!temps.IsDefaultOrEmpty)
{
throw ExceptionUtilities.UnexpectedValue(temps.Length);
}
rewrittenObjectCreation = node.UpdateArgumentsAndInitializer(rewrittenArguments, MakeObjectCreationInitializerForExpressionTree(node.InitializerExpressionOpt), changeTypeOpt: node.Constructor.ContainingType);
if (node.Type.IsInterfaceType())
{
Debug.Assert(rewrittenObjectCreation.Type == ((NamedTypeSymbol)node.Type).ComImportCoClass);
rewrittenObjectCreation = MakeConversion(rewrittenObjectCreation, node.Type, false, false);
}
return rewrittenObjectCreation;
}
rewrittenObjectCreation = node.UpdateArgumentsAndInitializer(rewrittenArguments, newInitializerExpression: null, changeTypeOpt: node.Constructor.ContainingType);
// replace "new S()" with a default struct ctor with "default(S)"
if (node.Constructor.IsDefaultValueTypeConstructor())
{
rewrittenObjectCreation = new BoundDefaultOperator(rewrittenObjectCreation.Syntax, rewrittenObjectCreation.Type);
}
if (!temps.IsDefaultOrEmpty)
{
rewrittenObjectCreation = new BoundSequence(
node.Syntax,
temps,
ImmutableArray<BoundExpression>.Empty,
rewrittenObjectCreation,
node.Type);
}
if (node.Type.IsInterfaceType())
{
Debug.Assert(rewrittenObjectCreation.Type == ((NamedTypeSymbol)node.Type).ComImportCoClass);
rewrittenObjectCreation = MakeConversion(rewrittenObjectCreation, node.Type, false, false);
}
if (node.InitializerExpressionOpt == null || node.InitializerExpressionOpt.HasErrors)
{
return rewrittenObjectCreation;
}
return MakeObjectCreationWithInitializer(node.Syntax, rewrittenObjectCreation, node.InitializerExpressionOpt, node.Type);
}
示例14: MakeNewT
private BoundExpression MakeNewT(CSharpSyntaxNode syntax, TypeParameterSymbol typeParameter)
{
// How "new T()" is rewritten depends on whether T is known to be a value
// type, a reference type, or neither (see OperatorRewriter::VisitNEWTYVAR).
if (typeParameter.IsValueType)
{
// "new T()" rewritten as: "default(T)".
return new BoundDefaultOperator(syntax, type: typeParameter);
}
// For types not known to be value types, "new T()" requires
// Activator.CreateInstance<T>().
MethodSymbol method;
if (!this.TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Activator__CreateInstance_T, out method))
{
return new BoundDefaultOperator(syntax, null, type: typeParameter, hasErrors: true);
}
Debug.Assert((object)method != null);
method = method.Construct(ImmutableArray.Create<TypeSymbol>(typeParameter));
var createInstanceCall = new BoundCall(
syntax,
null,
method,
ImmutableArray<BoundExpression>.Empty,
default(ImmutableArray<string>),
default(ImmutableArray<RefKind>),
isDelegateCall: false,
expanded: false,
invokedAsExtensionMethod: false,
argsToParamsOpt: default(ImmutableArray<int>),
resultKind: LookupResultKind.Viable,
type: typeParameter);
if (typeParameter.IsReferenceType)
{
// "new T()" is rewritten as: "Activator.CreateInstance<T>()".
return createInstanceCall;
}
else
{
// "new T()" is rewritten as: "(null == (object)default(T)) ? Activator.CreateInstance<T>() : default(T)".
var defaultT = new BoundDefaultOperator(syntax, type: typeParameter);
return new BoundConditionalOperator(
syntax,
MakeNullCheck(
syntax: syntax,
rewrittenExpr: MakeConversion(
syntax: syntax,
rewrittenOperand: defaultT,
conversionKind: ConversionKind.Boxing,
rewrittenType: this.compilation.GetSpecialType(SpecialType.System_Object),
@checked: false),
operatorKind: BinaryOperatorKind.Equal),
createInstanceCall,
defaultT,
constantValueOpt: null,
type: typeParameter);
}
}
示例15: GetDefaultParameterValue
private BoundExpression GetDefaultParameterValue(CSharpSyntaxNode syntax, ParameterSymbol parameter)
{
TypeSymbol parameterType = parameter.Type;
ConstantValue defaultConstantValue = parameter.ExplicitDefaultConstantValue;
BoundExpression defaultValue;
SourceLocation callerSourceLocation;
if (parameter.IsCallerLineNumber && ((callerSourceLocation = GetCallerLocation(syntax)) != null))
{
int line = callerSourceLocation.SourceTree.GetDisplayLineNumber(callerSourceLocation.SourceSpan);
BoundExpression lineLiteral = MakeLiteral(syntax, ConstantValue.Create(line), compilation.GetSpecialType(SpecialType.System_Int32));
if (parameterType.IsNullableType())
{
defaultValue = MakeConversion(lineLiteral, parameterType.GetNullableUnderlyingType(), false);
// wrap it in a nullable ctor.
defaultValue = new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor),
defaultValue);
}
else
{
defaultValue = MakeConversion(lineLiteral, parameterType, false);
}
}
else if (parameter.IsCallerFilePath && ((callerSourceLocation = GetCallerLocation(syntax)) != null))
{
string path = callerSourceLocation.SourceTree.GetDisplayPath(callerSourceLocation.SourceSpan, compilation.Options.SourceReferenceResolver);
BoundExpression memberNameLiteral = MakeLiteral(syntax, ConstantValue.Create(path), compilation.GetSpecialType(SpecialType.System_String));
defaultValue = MakeConversion(memberNameLiteral, parameterType, false);
}
else if (parameter.IsCallerMemberName && ((callerSourceLocation = GetCallerLocation(syntax)) != null))
{
string memberName = this.factory.TopLevelMethod.GetMemberCallerName();
BoundExpression memberNameLiteral = MakeLiteral(syntax, ConstantValue.Create(memberName), compilation.GetSpecialType(SpecialType.System_String));
defaultValue = MakeConversion(memberNameLiteral, parameterType, false);
}
else if (defaultConstantValue == ConstantValue.NotAvailable)
{
// There is no constant value given for the parameter in source/metadata.
if (parameterType.IsDynamic() || parameterType.SpecialType == SpecialType.System_Object)
{
// We have something like M([Optional] object x). We have special handling for such situations.
defaultValue = GetDefaultParameterSpecial(syntax, parameter);
}
else
{
// The argument to M([Optional] int x) becomes default(int)
defaultValue = new BoundDefaultOperator(syntax, parameterType);
}
}
else if (defaultConstantValue.IsNull && parameterType.IsValueType)
{
// We have something like M(int? x = null) or M(S x = default(S)),
// so replace the argument with default(int?).
defaultValue = new BoundDefaultOperator(syntax, parameterType);
}
else if (parameterType.IsNullableType())
{
// We have something like M(double? x = 1.23), so replace the argument
// with new double?(1.23).
TypeSymbol constantType = compilation.GetSpecialType(defaultConstantValue.SpecialType);
defaultValue = MakeLiteral(syntax, defaultConstantValue, constantType);
// The parameter's underlying type might not match the constant type. For example, we might have
// a default value of 5 (an integer) but a parameter type of decimal?.
defaultValue = MakeConversion(defaultValue, parameterType.GetNullableUnderlyingType(), @checked: false, acceptFailingConversion: true);
// Finally, wrap it in a nullable ctor.
defaultValue = new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor),
defaultValue);
}
else if (defaultConstantValue.IsNull || defaultConstantValue.IsBad)
{
defaultValue = MakeLiteral(syntax, defaultConstantValue, parameterType);
}
else
{
// We have something like M(double = 1.23), so replace the argument with 1.23.
TypeSymbol constantType = compilation.GetSpecialType(defaultConstantValue.SpecialType);
defaultValue = MakeLiteral(syntax, defaultConstantValue, constantType);
// The parameter type might not match the constant type.
defaultValue = MakeConversion(defaultValue, parameterType, @checked: false, acceptFailingConversion: true);
}
return defaultValue;
}