1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
5
using System.Collections;
6
using ICSharpCode.NRefactory.Ast;
7
using B = Boo.Lang.Compiler.Ast;
9
namespace NRefactoryToBooConverter
11
partial class ConvertVisitor
13
void ConvertExpressions(IEnumerable input, B.ExpressionCollection output)
15
foreach (Expression e in input) {
16
B.Expression expr = ConvertExpression(e);
23
B.Expression ConvertExpression(Expression expr)
27
return (B.Expression)expr.AcceptVisitor(this, null);
30
B.Expression MakeReferenceExpression(TypeReference typeRef)
32
if (typeRef.IsArrayType)
33
return new B.TypeofExpression(GetLexicalInfo(typeRef), ConvertTypeReference(typeRef));
34
B.SimpleTypeReference t = (B.SimpleTypeReference)ConvertTypeReference(typeRef);
35
B.ReferenceExpression r = MakeReferenceExpression(t.Name);
36
if (t is B.GenericTypeReference) {
37
B.GenericReferenceExpression gr = new B.GenericReferenceExpression(GetLexicalInfo(typeRef));
39
foreach (B.TypeReference tr in ((B.GenericTypeReference)t).GenericArguments) {
40
gr.GenericArguments.Add(tr);
48
B.ReferenceExpression MakeReferenceExpression(string fullName)
50
string[] parts = fullName.Split('.');
51
B.ReferenceExpression r = new B.ReferenceExpression(lastLexicalInfo, parts[0]);
52
for (int i = 1; i < parts.Length; i++)
53
r = new B.MemberReferenceExpression(lastLexicalInfo, r, parts[i]);
57
B.MethodInvocationExpression MakeMethodCall(string fullName, params B.Expression[] arguments)
59
return new B.MethodInvocationExpression(MakeReferenceExpression(fullName), arguments);
62
public object VisitPrimitiveExpression(PrimitiveExpression pe, object data)
64
object val = pe.Value;
66
return new B.NullLiteralExpression(GetLexicalInfo(pe));
69
return new B.StringLiteralExpression(GetLexicalInfo(pe), (string)val);
72
return new B.CharLiteralExpression(GetLexicalInfo(pe), ((char)val).ToString());
75
return new B.BoolLiteralExpression(GetLexicalInfo(pe), (bool)val);
78
AddWarning(pe, "Converting byte literal to int literal");
79
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (byte)val, false);
82
AddWarning(pe, "Converting short literal to int literal");
83
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (short)val, false);
86
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (int)val, false);
89
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (long)val, true);
92
AddWarning(pe, "Converting sbyte literal to int literal");
93
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (sbyte)val, false);
96
AddWarning(pe, "Converting ushort literal to int literal");
97
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (ushort)val, false);
100
AddWarning(pe, "Converting uint literal to int/long literal");
101
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (uint)val);
104
AddWarning(pe, "Converting ulong literal to long literal");
105
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (long)((ulong)val), true);
108
return new B.DoubleLiteralExpression(GetLexicalInfo(pe), (float)val, true);
111
return new B.DoubleLiteralExpression(GetLexicalInfo(pe), (double)val, false);
113
if (val is decimal) {
114
AddWarning(pe, "Converting decimal literal to double literal");
115
return new B.DoubleLiteralExpression(GetLexicalInfo(pe), (double)(decimal)val);
117
AddError(pe, "Unknown primitive literal of type " + val.GetType().FullName);
121
public object VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data)
123
AddError(namedArgumentExpression, "Named arguments are not supported in boo. (argument name was " + namedArgumentExpression.Name + ")");
124
return namedArgumentExpression.Expression.AcceptVisitor(this, data);
127
public object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
129
return new B.ReferenceExpression(GetLexicalInfo(identifierExpression), identifierExpression.Identifier);
132
public object VisitMemberReferenceExpression(MemberReferenceExpression mre, object data)
134
B.Expression target = null;
135
if (mre.TargetObject is TypeReferenceExpression) {
136
// not typeof, so this is something like int.Parse() or Class<string>.StaticMethod
137
TypeReference typeRef = ((TypeReferenceExpression)mre.TargetObject).TypeReference;
138
if (!typeRef.IsArrayType)
139
target = MakeReferenceExpression(typeRef);
141
if (target == null) {
142
target = (B.Expression)mre.TargetObject.AcceptVisitor(this, data);
143
if (target == null) return null;
145
return new B.MemberReferenceExpression(GetLexicalInfo(mre), target, mre.MemberName);
148
public object VisitClassReferenceExpression(ClassReferenceExpression classReferenceExpression, object data)
150
// VB's MyClass.Method references methods in the CURRENT class, ignoring overrides!!!
151
// that is supported neither by C# nor Boo.
152
// Most of the time, "Me"="self" should also do the job.
153
AddWarning(classReferenceExpression, "Class reference is not supported, replaced with self reference.");
154
return new B.SelfLiteralExpression(GetLexicalInfo(classReferenceExpression));
157
B.BinaryOperatorType ConvertOperator(AssignmentOperatorType op, out bool isInPlace)
161
case AssignmentOperatorType.Add:
162
return B.BinaryOperatorType.InPlaceAddition;
163
case AssignmentOperatorType.Assign:
164
return B.BinaryOperatorType.Assign;
165
case AssignmentOperatorType.BitwiseAnd:
166
return B.BinaryOperatorType.InPlaceBitwiseAnd;
167
case AssignmentOperatorType.BitwiseOr:
168
return B.BinaryOperatorType.InPlaceBitwiseOr;
169
case AssignmentOperatorType.ConcatString:
170
return B.BinaryOperatorType.InPlaceAddition;
171
case AssignmentOperatorType.Divide:
172
return B.BinaryOperatorType.InPlaceDivision;
173
case AssignmentOperatorType.DivideInteger:
174
return B.BinaryOperatorType.InPlaceDivision;
175
case AssignmentOperatorType.ExclusiveOr:
176
return B.BinaryOperatorType.InPlaceExclusiveOr;
177
case AssignmentOperatorType.Modulus:
179
return B.BinaryOperatorType.Modulus;
180
case AssignmentOperatorType.Multiply:
181
return B.BinaryOperatorType.InPlaceMultiply;
182
case AssignmentOperatorType.Power:
184
return B.BinaryOperatorType.Exponentiation;
185
case AssignmentOperatorType.ShiftLeft:
186
return B.BinaryOperatorType.InPlaceShiftLeft;
187
case AssignmentOperatorType.ShiftRight:
188
return B.BinaryOperatorType.InPlaceShiftRight;
189
case AssignmentOperatorType.Subtract:
190
return B.BinaryOperatorType.InPlaceSubtraction;
192
return B.BinaryOperatorType.None;
196
public object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data)
198
B.Expression left = ConvertExpression(assignmentExpression.Left);
199
B.Expression right = ConvertExpression(assignmentExpression.Right);
201
B.BinaryOperatorType op = ConvertOperator(assignmentExpression.Op, out isInPlace);
202
if (op == B.BinaryOperatorType.None) {
203
AddError(assignmentExpression, "Unknown operator.");
207
// convert L <OP>= R to L = L OP R
208
right = new B.BinaryExpression(GetLexicalInfo(assignmentExpression), op, left, right);
209
op = B.BinaryOperatorType.Assign;
211
return new B.BinaryExpression(GetLexicalInfo(assignmentExpression), op, left, right);
214
B.BinaryOperatorType ConvertOperator(BinaryOperatorType op)
217
case BinaryOperatorType.Add:
218
return B.BinaryOperatorType.Addition;
219
case BinaryOperatorType.BitwiseAnd:
220
return B.BinaryOperatorType.BitwiseAnd;
221
case BinaryOperatorType.BitwiseOr:
222
return B.BinaryOperatorType.BitwiseOr;
223
case BinaryOperatorType.Concat:
224
return B.BinaryOperatorType.Addition;
225
case BinaryOperatorType.Divide:
226
return B.BinaryOperatorType.Division;
227
case BinaryOperatorType.DivideInteger:
228
return B.BinaryOperatorType.Division;
229
case BinaryOperatorType.Equality:
230
return B.BinaryOperatorType.Equality;
231
case BinaryOperatorType.ExclusiveOr:
232
return B.BinaryOperatorType.ExclusiveOr;
233
case BinaryOperatorType.GreaterThan:
234
return B.BinaryOperatorType.GreaterThan;
235
case BinaryOperatorType.GreaterThanOrEqual:
236
return B.BinaryOperatorType.GreaterThanOrEqual;
237
case BinaryOperatorType.InEquality:
238
return B.BinaryOperatorType.Inequality;
239
case BinaryOperatorType.LessThan:
240
return B.BinaryOperatorType.LessThan;
241
case BinaryOperatorType.LessThanOrEqual:
242
return B.BinaryOperatorType.LessThanOrEqual;
243
case BinaryOperatorType.Like:
244
return B.BinaryOperatorType.Match;
245
case BinaryOperatorType.LogicalAnd:
246
return B.BinaryOperatorType.And;
247
case BinaryOperatorType.LogicalOr:
248
return B.BinaryOperatorType.Or;
249
case BinaryOperatorType.Modulus:
250
return B.BinaryOperatorType.Modulus;
251
case BinaryOperatorType.Multiply:
252
return B.BinaryOperatorType.Multiply;
253
case BinaryOperatorType.NullCoalescing:
254
return B.BinaryOperatorType.Or;
255
case BinaryOperatorType.Power:
256
return B.BinaryOperatorType.Exponentiation;
257
case BinaryOperatorType.ReferenceEquality:
258
return B.BinaryOperatorType.ReferenceEquality;
259
case BinaryOperatorType.ReferenceInequality:
260
return B.BinaryOperatorType.ReferenceInequality;
261
case BinaryOperatorType.ShiftLeft:
262
return B.BinaryOperatorType.ShiftLeft;
263
case BinaryOperatorType.ShiftRight:
264
return B.BinaryOperatorType.ShiftRight;
265
case BinaryOperatorType.Subtract:
266
return B.BinaryOperatorType.Subtraction;
268
return B.BinaryOperatorType.None;
273
B.UnaryOperatorType ConvertOperator(UnaryOperatorType op)
276
case UnaryOperatorType.BitNot:
277
return B.UnaryOperatorType.OnesComplement;
278
case UnaryOperatorType.Not:
279
return B.UnaryOperatorType.LogicalNot;
280
case UnaryOperatorType.Decrement:
281
return B.UnaryOperatorType.Decrement;
282
case UnaryOperatorType.Increment:
283
return B.UnaryOperatorType.Increment;
284
case UnaryOperatorType.Minus:
285
return B.UnaryOperatorType.UnaryNegation;
286
case UnaryOperatorType.PostDecrement:
287
return B.UnaryOperatorType.PostDecrement;
288
case UnaryOperatorType.PostIncrement:
289
return B.UnaryOperatorType.PostIncrement;
291
return B.UnaryOperatorType.None;
295
public object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
297
B.Expression left = ConvertExpression(binaryOperatorExpression.Left);
298
B.Expression right = ConvertExpression(binaryOperatorExpression.Right);
299
B.BinaryOperatorType op = ConvertOperator(binaryOperatorExpression.Op);
300
if (op == B.BinaryOperatorType.None) {
301
AddError(binaryOperatorExpression, "Unknown operator.");
304
// if (binaryOperatorExpression.Op == BinaryOperatorType.DivideInteger) {
305
// AddWarning(binaryOperatorExpression, "Integer division converted to normal division.");
307
return new B.BinaryExpression(GetLexicalInfo(binaryOperatorExpression), op, left, right);
310
public object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
312
B.Expression expr = ConvertExpression(unaryOperatorExpression.Expression);
313
if (unaryOperatorExpression.Op == UnaryOperatorType.Plus)
315
B.UnaryOperatorType op = ConvertOperator(unaryOperatorExpression.Op);
316
if (op == B.UnaryOperatorType.None) {
317
AddError(unaryOperatorExpression, "Unknown operator.");
320
return new B.UnaryExpression(GetLexicalInfo(unaryOperatorExpression), op, expr);
323
public object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
325
return ConvertExpression(parenthesizedExpression.Expression);
328
public object VisitInvocationExpression(InvocationExpression ie, object data)
330
B.Expression e = ConvertExpression(ie.TargetObject);
333
if (settings.IsVisualBasic && ie.TargetObject is IdentifierExpression && currentStatement != null) {
334
VariableResolver resolver = new VariableResolver(nameComparer);
335
TypeReference typeRef = resolver.FindType((ie.TargetObject as IdentifierExpression).Identifier, currentStatement);
336
if (typeRef != null && typeRef.IsArrayType) {
337
// Visual Basic: indexer expression
338
B.SlicingExpression s = new B.SlicingExpression(GetLexicalInfo(ie));
340
foreach (Expression expr in ie.Arguments) {
341
s.Indices.Add(new B.Slice(ConvertExpression(expr)));
346
B.MethodInvocationExpression r = new B.MethodInvocationExpression(GetLexicalInfo(ie), e);
347
foreach (Expression expr in ie.Arguments) {
348
e = ConvertExpression(expr);
356
public object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
358
TypeReference t = objectCreateExpression.CreateType;
360
throw new ApplicationException("ObjectCreateExpression cannot be called with an ArrayType");
362
// HACK: Tricking out event handlers
363
if (t.Type.EndsWith("EventHandler") && objectCreateExpression.Parameters.Count == 1)
364
return ConvertExpression((Expression)objectCreateExpression.Parameters[0]);
366
B.MethodInvocationExpression mie = new B.MethodInvocationExpression(GetLexicalInfo(objectCreateExpression), MakeReferenceExpression(t));
367
ConvertExpressions(objectCreateExpression.Parameters, mie.Arguments);
371
public object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data)
373
return MakeReferenceExpression(typeReferenceExpression.TypeReference);
376
public object VisitSizeOfExpression(SizeOfExpression sizeOfExpression, object data)
378
AddError(sizeOfExpression, "sizeof is not supported.");
382
public object VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data)
384
AddError(defaultValueExpression, "default() is not supported.");
388
public object VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data)
390
return new B.TypeofExpression(GetLexicalInfo(typeOfExpression), ConvertTypeReference(typeOfExpression.TypeReference));
393
public object VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data)
395
return new B.BinaryExpression(GetLexicalInfo(typeOfIsExpression), B.BinaryOperatorType.TypeTest,
396
ConvertExpression(typeOfIsExpression.Expression),
397
new B.TypeofExpression(GetLexicalInfo(typeOfIsExpression), ConvertTypeReference(typeOfIsExpression.TypeReference)));
400
public object VisitAddressOfExpression(AddressOfExpression addressOfExpression, object data)
402
// Boo can reference methods directly
403
return ConvertExpression(addressOfExpression.Expression);
406
public object VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data)
408
AddError(pointerReferenceExpression, "Pointers are not supported.");
412
public object VisitCastExpression(CastExpression castExpression, object data)
414
switch (castExpression.CastType) {
416
case CastType.Conversion:
417
case CastType.PrimitiveConversion:
418
return new B.CastExpression(GetLexicalInfo(castExpression),
419
ConvertExpression(castExpression.Expression),
420
ConvertTypeReference(castExpression.CastTo));
421
case CastType.TryCast:
422
return new B.TryCastExpression(GetLexicalInfo(castExpression),
423
ConvertExpression(castExpression.Expression),
424
ConvertTypeReference(castExpression.CastTo));
426
AddError(castExpression, "Unknown cast: " + castExpression);
431
public object VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data)
433
AddError(stackAllocExpression, "StackAlloc is not supported.");
437
public object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data)
439
return new B.SelfLiteralExpression(GetLexicalInfo(thisReferenceExpression));
442
public object VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data)
444
return new B.SuperLiteralExpression(GetLexicalInfo(baseReferenceExpression));
447
public object VisitDirectionExpression(DirectionExpression directionExpression, object data)
449
// boo does not need to specify the direction when calling out/ref methods
450
return ConvertExpression(directionExpression.Expression);
453
public object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data)
455
if (!arrayCreateExpression.ArrayInitializer.IsNull) {
456
B.ArrayLiteralExpression ale = ConvertArrayLiteralExpression(arrayCreateExpression.ArrayInitializer);
457
if (!arrayCreateExpression.IsImplicitlyTyped) {
458
ale.Type = (B.ArrayTypeReference)ConvertTypeReference(arrayCreateExpression.CreateType);
462
string builtInName = (arrayCreateExpression.Arguments.Count > 1) ? "matrix" : "array";
463
B.MethodInvocationExpression mie = new B.MethodInvocationExpression(GetLexicalInfo(arrayCreateExpression),
464
MakeReferenceExpression(builtInName));
465
TypeReference elementType = arrayCreateExpression.CreateType.Clone();
466
int[] newRank = new int[elementType.RankSpecifier.Length - 1];
467
for (int i = 0; i < newRank.Length; i++)
468
newRank[i] = elementType.RankSpecifier[i + 1];
469
elementType.RankSpecifier = newRank;
470
mie.Arguments.Add(MakeReferenceExpression(elementType));
471
ConvertExpressions(arrayCreateExpression.Arguments, mie.Arguments);
475
public object VisitCollectionInitializerExpression(CollectionInitializerExpression aie, object data)
477
return ConvertArrayLiteralExpression(aie);
480
B.ArrayLiteralExpression ConvertArrayLiteralExpression(CollectionInitializerExpression aie)
482
B.ArrayLiteralExpression dims = new B.ArrayLiteralExpression(GetLexicalInfo(aie));
483
ConvertExpressions(aie.CreateExpressions, dims.Items);
487
public object VisitIndexerExpression(IndexerExpression indexerExpression, object data)
489
B.SlicingExpression s = new B.SlicingExpression(GetLexicalInfo(indexerExpression));
490
s.Target = ConvertExpression(indexerExpression.TargetObject);
491
foreach (Expression expr in indexerExpression.Indexes) {
492
s.Indices.Add(new B.Slice(ConvertExpression(expr)));
497
public object VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data)
499
B.BlockExpression cbe = new B.BlockExpression(GetLexicalInfo(anonymousMethodExpression));
500
cbe.EndSourceLocation = GetLocation(anonymousMethodExpression.EndLocation);
501
cbe.Body = ConvertBlock(anonymousMethodExpression.Body);
502
ConvertParameters(anonymousMethodExpression.Parameters, cbe.Parameters);
506
public object VisitLambdaExpression(LambdaExpression lambdaExpression, object data)
508
B.BlockExpression cbe = new B.BlockExpression(GetLexicalInfo(lambdaExpression));
509
cbe.EndSourceLocation = GetLocation(lambdaExpression.EndLocation);
510
if (lambdaExpression.StatementBody.IsNull) {
511
cbe.Body = new B.Block();
512
cbe.Body.Add(new B.ReturnStatement(ConvertExpression(lambdaExpression.ExpressionBody)));
514
cbe.Body = ConvertBlock(lambdaExpression.StatementBody);
516
ConvertParameters(lambdaExpression.Parameters, cbe.Parameters);
520
public object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data)
522
B.ConditionalExpression te = new B.ConditionalExpression(GetLexicalInfo(conditionalExpression));
523
te.Condition = ConvertExpression(conditionalExpression.Condition);
524
te.TrueValue = ConvertExpression(conditionalExpression.TrueExpression);
525
te.FalseValue = ConvertExpression(conditionalExpression.FalseExpression);
529
public object VisitCheckedExpression(CheckedExpression checkedExpression, object data)
531
AddError(checkedExpression, "Using 'checked' inside an expression is not supported by boo, " +
532
"use the checked {} block instead.");
533
return MakeMethodCall("checked", ConvertExpression(checkedExpression.Expression));
536
public object VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data)
538
AddError(uncheckedExpression, "Using 'unchecked' inside an expression is not supported by boo, " +
539
"use the unchecked {} block instead.");
540
return MakeMethodCall("unchecked", ConvertExpression(uncheckedExpression.Expression));