private BoundNode RewriteStringConcatenation(BoundBinaryOperator node) { // UNDONE: We need to make this more sophisticated. For example, we should // UNDONE: be rewriting (M() + "A") + ("B" + N()) as // UNDONE: String.Concat(M(), "AB", N()). // UNDONE: We have many overloads of String.Concat to choose from: that // UNDONE: take one, two, three, four strings, that take params arrays // UNDONE: in strings and objects, and so on. See the native compiler // UNDONE: string rewriter for details. // UNDONE: For now, just to get this going let's do it the easy way; // UNDONE: we'll just generate calls to String.Concat(string, string) // UNDONE: or String.Concat(object, object) as appropriate. Debug.Assert(node != null); Debug.Assert(node.ConstantValueOpt == null); SpecialMember member = (node.OperatorKind == BinaryOperatorKind.StringConcatenation) ? SpecialMember.System_String__ConcatStringString : SpecialMember.System_String__ConcatObjectObject; var method = (MethodSymbol)this.compilation.Assembly.GetSpecialTypeMember(member); // UNDONE: Handle the bizarre error case where we don't have the expected string concat methods. Debug.Assert(method != null); return(Visit(BoundCall.SynthesizedCall(null, method, node.Left, node.Right))); }
private BoundNode RewriteDelegateOperation(BoundBinaryOperator node, SpecialMember member) { Debug.Assert(node != null); var method = (MethodSymbol)this.compilation.Assembly.GetSpecialTypeMember(member); // UNDONE: Handle the bizarre error case where we don't have the expected methods. Debug.Assert(method != null); BoundExpression call = BoundCall.SynthesizedCall(null, method, node.Left, node.Right); BoundExpression result = method.ReturnType.SpecialType == SpecialType.System_Delegate ? BoundConversion.SynthesizedConversion(call, ConversionKind.ExplicitReference, node.Type) : call; return(Visit(result)); }
private BoundNode RewriteStringEquality(BoundBinaryOperator node, SpecialMember member) { Debug.Assert(node != null); Debug.Assert(node.ConstantValueOpt == null); if (node.Left.ConstantValue == ConstantValue.Null || node.Right.ConstantValue == ConstantValue.Null) { return(base.VisitBinaryOperator(node)); } var method = (MethodSymbol)this.compilation.Assembly.GetSpecialTypeMember(member); Debug.Assert(method != null); return(Visit(BoundCall.SynthesizedCall(null, method, node.Left, node.Right))); }
public override BoundNode VisitPropertyAccess(BoundPropertyAccess node) { // Avoid rewriting if node has errors since the accessor may not exist. if (node.HasErrors) { return(base.VisitPropertyAccess(node)); } // Rewrite property access into call to getter. var property = node.PropertySymbol.GetBaseProperty(); var getMethod = property.GetMethod; Debug.Assert(getMethod != null); Debug.Assert(getMethod.Parameters.Count == 0); Debug.Assert(!getMethod.IsOverride); var rewrittenReceiver = (BoundExpression)Visit(node.ReceiverOpt); return(BoundCall.SynthesizedCall(rewrittenReceiver, getMethod)); }
private BoundExpression VisitAssignmentOperator(BoundAssignmentOperator node, bool used) { // Avoid rewriting if node has errors since at least // one of the operands is invalid. if (node.HasErrors) { return(node); } var propertyAccessor = node.Left as BoundPropertyAccess; if (propertyAccessor == null) { return((BoundExpression)base.VisitAssignmentOperator(node)); } // Rewrite property assignment into call to setter. var property = propertyAccessor.PropertySymbol.GetBaseProperty(); var setMethod = property.SetMethod; Debug.Assert(setMethod != null); Debug.Assert(setMethod.Parameters.Count == 1); Debug.Assert(!setMethod.IsOverride); var rewrittenReceiver = (BoundExpression)Visit(propertyAccessor.ReceiverOpt); var rewrittenArgument = (BoundExpression)Visit(node.Right); if (used) { // Save expression value to a temporary before calling the // setter, and restore the temporary after the setter, so the // assignment can be used as an embedded expression. var exprType = rewrittenArgument.Type; var tempSymbol = new TempLocalSymbol(exprType, RefKind.None, containingSymbol); var tempLocal = new BoundLocal(null, null, tempSymbol, null, exprType); var saveTemp = new BoundAssignmentOperator( null, null, tempLocal, rewrittenArgument, exprType); var call = BoundCall.SynthesizedCall( rewrittenReceiver, setMethod, saveTemp); return(new BoundSequence( node.Syntax, node.SyntaxTree, ReadOnlyArray <LocalSymbol> .CreateFrom(tempSymbol), ReadOnlyArray <BoundExpression> .CreateFrom(call), tempLocal, exprType)); } else { return(BoundCall.SynthesizedCall( rewrittenReceiver, setMethod, rewrittenArgument)); } }