Skip to content

Commit 1e76fe7

Browse files
Initial copy
1 parent 01da6ad commit 1e76fe7

1 file changed

Lines changed: 316 additions & 0 deletions

File tree

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Globalization;
4+
using System.Linq;
5+
using ICSharpCode.CodeConverter.Util;
6+
using ICSharpCode.CodeConverter.Util.FromRoslyn;
7+
using Microsoft.CodeAnalysis;
8+
using Microsoft.CodeAnalysis.CSharp;
9+
using Microsoft.CodeAnalysis.CSharp.Syntax;
10+
using Microsoft.VisualBasic.CompilerServices;
11+
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
12+
using SyntaxKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind;
13+
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
14+
using VBSyntaxKind = Microsoft.CodeAnalysis.VisualBasic.SyntaxKind;
15+
using VBasic = Microsoft.CodeAnalysis.VisualBasic;
16+
17+
namespace ICSharpCode.CodeConverter.CSharp
18+
{
19+
20+
public class BuiltInVisualBasicOperatorSubsitutions
21+
{
22+
/// <summary>
23+
/// Started as a paste of:
24+
/// https://github.com/dotnet/roslyn/blob/master/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_BinaryOperators.vb#L233-L464
25+
/// See file history to understand any changes
26+
/// </summary>
27+
private BoundExpression TransformRewrittenBinaryOperator(BoundBinaryOperator node)
28+
{
29+
var opKind = node.OperatorKind;
30+
Debug.Assert((opKind & BinaryOperatorKind.Lifted) == 0);
31+
var switchExpr = opKind & BinaryOperatorKind.OpMask;
32+
switch (switchExpr) {
33+
case BinaryOperatorKind.Is:
34+
case BinaryOperatorKind.IsNot: {
35+
node = node.Update(node.OperatorKind, ReplaceMyGroupCollectionPropertyGetWithUnderlyingField(node.Left), ReplaceMyGroupCollectionPropertyGetWithUnderlyingField(node.Right), node.Checked, node.ConstantValueOpt, node.Type);
36+
if (node.Left.Type is object && node.Left.Type.IsNullableType || node.Right.Type is object && node.Right.Type.IsNullableType) {
37+
return RewriteNullableIsOrIsNotOperator(node);
38+
}
39+
40+
break;
41+
}
42+
43+
case BinaryOperatorKind.Concatenate: // Concat needs to be done before expr trees, so in LocalRewriter instead of VBSemanticsRewriter
44+
{
45+
if (node.Type.IsObjectType()) {
46+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__ConcatenateObjectObjectObject);
47+
} else {
48+
return RewriteConcatenateOperator(node);
49+
}
50+
51+
break;
52+
}
53+
54+
case BinaryOperatorKind.Like: {
55+
if (node.Left.Type.IsObjectType()) {
56+
return RewriteLikeOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_LikeOperator__LikeObjectObjectObjectCompareMethod);
57+
} else {
58+
return RewriteLikeOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_LikeOperator__LikeStringStringStringCompareMethod);
59+
}
60+
61+
break;
62+
}
63+
64+
case BinaryOperatorKind.Equals: {
65+
var leftType = node.Left.Type;
66+
// NOTE: For some reason Dev11 seems to still ignore inside the expression tree the fact that the target
67+
// type of the binary operator is Boolean and used Object op Object => Object helpers even in this case
68+
// despite what is said in comments in RuntimeMembers CodeGenerator::GetHelperForObjRelOp
69+
// TODO: Recheck
70+
71+
if (node.Type.IsObjectType() || this._inExpressionLambda && leftType.IsObjectType()) {
72+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__CompareObjectEqualObjectObjectBoolean);
73+
} else if (node.Type.IsBooleanType()) {
74+
if (leftType.IsObjectType()) {
75+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__ConditionalCompareObjectEqualObjectObjectBoolean);
76+
} else if (leftType.IsStringType()) {
77+
return RewriteStringComparisonOperator(node);
78+
} else if (leftType.IsDecimalType()) {
79+
return RewriteDecimalComparisonOperator(node);
80+
} else if (leftType.IsDateTimeType()) {
81+
return RewriteDateComparisonOperator(node);
82+
}
83+
}
84+
85+
break;
86+
}
87+
88+
case BinaryOperatorKind.NotEquals: {
89+
var leftType = node.Left.Type;
90+
// NOTE: See comment above
91+
92+
if (node.Type.IsObjectType() || this._inExpressionLambda && leftType.IsObjectType()) {
93+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__CompareObjectNotEqualObjectObjectBoolean);
94+
} else if (node.Type.IsBooleanType()) {
95+
if (leftType.IsObjectType()) {
96+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__ConditionalCompareObjectNotEqualObjectObjectBoolean);
97+
} else if (leftType.IsStringType()) {
98+
return RewriteStringComparisonOperator(node);
99+
} else if (leftType.IsDecimalType()) {
100+
return RewriteDecimalComparisonOperator(node);
101+
} else if (leftType.IsDateTimeType()) {
102+
return RewriteDateComparisonOperator(node);
103+
}
104+
}
105+
106+
break;
107+
}
108+
109+
case BinaryOperatorKind.LessThanOrEqual: {
110+
var leftType = node.Left.Type;
111+
// NOTE: See comment above
112+
113+
if (node.Type.IsObjectType() || this._inExpressionLambda && leftType.IsObjectType()) {
114+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__CompareObjectLessEqualObjectObjectBoolean);
115+
} else if (node.Type.IsBooleanType()) {
116+
if (leftType.IsObjectType()) {
117+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__ConditionalCompareObjectLessEqualObjectObjectBoolean);
118+
} else if (leftType.IsStringType()) {
119+
return RewriteStringComparisonOperator(node);
120+
} else if (leftType.IsDecimalType()) {
121+
return RewriteDecimalComparisonOperator(node);
122+
} else if (leftType.IsDateTimeType()) {
123+
return RewriteDateComparisonOperator(node);
124+
}
125+
}
126+
127+
break;
128+
}
129+
130+
case BinaryOperatorKind.GreaterThanOrEqual: {
131+
var leftType = node.Left.Type;
132+
// NOTE: See comment above
133+
134+
if (node.Type.IsObjectType() || this._inExpressionLambda && leftType.IsObjectType()) {
135+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__CompareObjectGreaterEqualObjectObjectBoolean);
136+
} else if (node.Type.IsBooleanType()) {
137+
if (leftType.IsObjectType()) {
138+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__ConditionalCompareObjectGreaterEqualObjectObjectBoolean);
139+
} else if (leftType.IsStringType()) {
140+
return RewriteStringComparisonOperator(node);
141+
} else if (leftType.IsDecimalType()) {
142+
return RewriteDecimalComparisonOperator(node);
143+
} else if (leftType.IsDateTimeType()) {
144+
return RewriteDateComparisonOperator(node);
145+
}
146+
}
147+
148+
break;
149+
}
150+
151+
case BinaryOperatorKind.LessThan: {
152+
var leftType = node.Left.Type;
153+
// NOTE: See comment above
154+
155+
if (node.Type.IsObjectType() || this._inExpressionLambda && leftType.IsObjectType()) {
156+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__CompareObjectLessObjectObjectBoolean);
157+
} else if (node.Type.IsBooleanType()) {
158+
if (leftType.IsObjectType()) {
159+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__ConditionalCompareObjectLessObjectObjectBoolean);
160+
} else if (leftType.IsStringType()) {
161+
return RewriteStringComparisonOperator(node);
162+
} else if (leftType.IsDecimalType()) {
163+
return RewriteDecimalComparisonOperator(node);
164+
} else if (leftType.IsDateTimeType()) {
165+
return RewriteDateComparisonOperator(node);
166+
}
167+
}
168+
169+
break;
170+
}
171+
172+
case BinaryOperatorKind.GreaterThan: {
173+
var leftType = node.Left.Type;
174+
// NOTE: See comment above
175+
176+
if (node.Type.IsObjectType() || this._inExpressionLambda && leftType.IsObjectType()) {
177+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__CompareObjectGreaterObjectObjectBoolean);
178+
} else if (node.Type.IsBooleanType()) {
179+
if (leftType.IsObjectType()) {
180+
return RewriteObjectComparisonOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__ConditionalCompareObjectGreaterObjectObjectBoolean);
181+
} else if (leftType.IsStringType()) {
182+
return RewriteStringComparisonOperator(node);
183+
} else if (leftType.IsDecimalType()) {
184+
return RewriteDecimalComparisonOperator(node);
185+
} else if (leftType.IsDateTimeType()) {
186+
return RewriteDateComparisonOperator(node);
187+
}
188+
}
189+
190+
break;
191+
}
192+
193+
case BinaryOperatorKind.Add: {
194+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
195+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__AddObjectObjectObject);
196+
} else if (node.Type.IsDecimalType()) {
197+
return RewriteDecimalBinaryOperator(node, SpecialMember.System_Decimal__AddDecimalDecimal);
198+
}
199+
200+
break;
201+
}
202+
203+
case BinaryOperatorKind.Subtract: {
204+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
205+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__SubtractObjectObjectObject);
206+
} else if (node.Type.IsDecimalType()) {
207+
return RewriteDecimalBinaryOperator(node, SpecialMember.System_Decimal__SubtractDecimalDecimal);
208+
}
209+
210+
break;
211+
}
212+
213+
case BinaryOperatorKind.Multiply: {
214+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
215+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__MultiplyObjectObjectObject);
216+
} else if (node.Type.IsDecimalType()) {
217+
return RewriteDecimalBinaryOperator(node, SpecialMember.System_Decimal__MultiplyDecimalDecimal);
218+
}
219+
220+
break;
221+
}
222+
223+
case BinaryOperatorKind.Modulo: {
224+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
225+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__ModObjectObjectObject);
226+
} else if (node.Type.IsDecimalType()) {
227+
return RewriteDecimalBinaryOperator(node, SpecialMember.System_Decimal__RemainderDecimalDecimal);
228+
}
229+
230+
break;
231+
}
232+
233+
case BinaryOperatorKind.Divide: {
234+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
235+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__DivideObjectObjectObject);
236+
} else if (node.Type.IsDecimalType()) {
237+
return RewriteDecimalBinaryOperator(node, SpecialMember.System_Decimal__DivideDecimalDecimal);
238+
}
239+
240+
break;
241+
}
242+
243+
case BinaryOperatorKind.IntegerDivide: {
244+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
245+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__IntDivideObjectObjectObject);
246+
}
247+
248+
break;
249+
}
250+
251+
case BinaryOperatorKind.Power: {
252+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
253+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__ExponentObjectObjectObject);
254+
} else {
255+
return RewritePowOperator(node);
256+
}
257+
258+
break;
259+
}
260+
261+
case BinaryOperatorKind.LeftShift: {
262+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
263+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__LeftShiftObjectObjectObject);
264+
}
265+
266+
break;
267+
}
268+
269+
case BinaryOperatorKind.RightShift: {
270+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
271+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__RightShiftObjectObjectObject);
272+
}
273+
274+
break;
275+
}
276+
277+
case BinaryOperatorKind.OrElse:
278+
case BinaryOperatorKind.AndAlso: {
279+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
280+
return RewriteObjectShortCircuitOperator(node);
281+
}
282+
283+
break;
284+
}
285+
286+
case BinaryOperatorKind.Xor: {
287+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
288+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__XorObjectObjectObject);
289+
}
290+
291+
break;
292+
}
293+
294+
case BinaryOperatorKind.Or: {
295+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
296+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__OrObjectObjectObject);
297+
}
298+
299+
break;
300+
}
301+
302+
case BinaryOperatorKind.And: {
303+
if (node.Type.IsObjectType() && !_inExpressionLambda) {
304+
return RewriteObjectBinaryOperator(node, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Operators__AndObjectObjectObject);
305+
}
306+
307+
break;
308+
}
309+
}
310+
311+
return node;
312+
}
313+
314+
315+
}
316+
}

0 commit comments

Comments
 (0)