You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
526 lines
20 KiB
526 lines
20 KiB
// <file> |
|
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> |
|
// <license see="prj:///doc/license.txt">GNU General Public License</license> |
|
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/> |
|
// <version>$Revision$</version> |
|
// </file> |
|
|
|
using System; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
using ICSharpCode.NRefactory.Parser; |
|
using ICSharpCode.NRefactory.Parser.AST; |
|
using Boo.Lang.Compiler; |
|
using B = Boo.Lang.Compiler.Ast; |
|
|
|
namespace NRefactoryToBooConverter |
|
{ |
|
partial class ConvertVisitor |
|
{ |
|
void ConvertExpressions(IEnumerable input, B.ExpressionCollection output) |
|
{ |
|
foreach (Expression e in input) { |
|
B.Expression expr = ConvertExpression(e); |
|
if (expr != null) { |
|
output.Add(expr); |
|
} |
|
} |
|
} |
|
|
|
B.Expression ConvertExpression(Expression expr) |
|
{ |
|
if (expr.IsNull) |
|
return null; |
|
return (B.Expression)expr.AcceptVisitor(this, null); |
|
} |
|
|
|
B.Expression MakeReferenceExpression(TypeReference typeRef) |
|
{ |
|
if (typeRef.IsArrayType) |
|
return new B.TypeofExpression(GetLexicalInfo(typeRef), ConvertTypeReference(typeRef)); |
|
B.SimpleTypeReference t = (B.SimpleTypeReference)ConvertTypeReference(typeRef); |
|
B.ReferenceExpression r = MakeReferenceExpression(t.Name); |
|
if (t is B.GenericTypeReference) { |
|
B.GenericReferenceExpression gr = new B.GenericReferenceExpression(GetLexicalInfo(typeRef)); |
|
gr.Target = r; |
|
foreach (B.TypeReference tr in ((B.GenericTypeReference)t).GenericArguments) { |
|
gr.GenericArguments.Add(tr); |
|
} |
|
return gr; |
|
} else { |
|
return r; |
|
} |
|
} |
|
|
|
B.ReferenceExpression MakeReferenceExpression(string fullName) |
|
{ |
|
string[] parts = fullName.Split('.'); |
|
B.ReferenceExpression r = new B.ReferenceExpression(lastLexicalInfo, parts[0]); |
|
for (int i = 1; i < parts.Length; i++) |
|
r = new B.MemberReferenceExpression(lastLexicalInfo, r, parts[i]); |
|
return r; |
|
} |
|
|
|
B.MethodInvocationExpression MakeMethodCall(string fullName, params B.Expression[] arguments) |
|
{ |
|
return new B.MethodInvocationExpression(MakeReferenceExpression(fullName), arguments); |
|
} |
|
|
|
public object Visit(PrimitiveExpression pe, object data) |
|
{ |
|
object val = pe.Value; |
|
if (val == null) { |
|
return new B.NullLiteralExpression(GetLexicalInfo(pe)); |
|
} |
|
if (val is string) { |
|
return new B.StringLiteralExpression(GetLexicalInfo(pe), (string)val); |
|
} |
|
if (val is char) { |
|
return new B.CharLiteralExpression(GetLexicalInfo(pe), ((char)val).ToString()); |
|
} |
|
if (val is bool) { |
|
return new B.BoolLiteralExpression(GetLexicalInfo(pe), (bool)val); |
|
} |
|
if (val is byte) { |
|
AddWarning(pe, "Converting byte literal to int literal"); |
|
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (byte)val, false); |
|
} |
|
if (val is short) { |
|
AddWarning(pe, "Converting short literal to int literal"); |
|
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (short)val, false); |
|
} |
|
if (val is int) { |
|
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (int)val, false); |
|
} |
|
if (val is long) { |
|
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (long)val, true); |
|
} |
|
if (val is sbyte) { |
|
AddWarning(pe, "Converting sbyte literal to int literal"); |
|
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (sbyte)val, false); |
|
} |
|
if (val is ushort) { |
|
AddWarning(pe, "Converting ushort literal to int literal"); |
|
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (ushort)val, false); |
|
} |
|
if (val is uint) { |
|
AddWarning(pe, "Converting uint literal to int/long literal"); |
|
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (uint)val); |
|
} |
|
if (val is ulong) { |
|
AddWarning(pe, "Converting ulong literal to long literal"); |
|
return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (long)((ulong)val), true); |
|
} |
|
if (val is float) { |
|
return new B.DoubleLiteralExpression(GetLexicalInfo(pe), (float)val, true); |
|
} |
|
if (val is double) { |
|
return new B.DoubleLiteralExpression(GetLexicalInfo(pe), (double)val, false); |
|
} |
|
AddError(pe, "Unknown primitive literal of type " + val.GetType().FullName); |
|
return null; |
|
} |
|
|
|
public object Visit(IdentifierExpression identifierExpression, object data) |
|
{ |
|
return new B.ReferenceExpression(GetLexicalInfo(identifierExpression), identifierExpression.Identifier); |
|
} |
|
|
|
public object Visit(FieldReferenceExpression fre, object data) |
|
{ |
|
B.Expression target = null; |
|
if (fre.TargetObject is TypeReferenceExpression) { |
|
// not typeof, so this is something like int.Parse() or Class<string>.StaticMethod |
|
TypeReference typeRef = ((TypeReferenceExpression)fre.TargetObject).TypeReference; |
|
if (!typeRef.IsArrayType) |
|
target = MakeReferenceExpression(typeRef); |
|
} |
|
if (target == null) { |
|
target = (B.Expression)fre.TargetObject.AcceptVisitor(this, data); |
|
if (target == null) return null; |
|
} |
|
return new B.MemberReferenceExpression(GetLexicalInfo(fre), target, fre.FieldName); |
|
} |
|
|
|
public object Visit(ClassReferenceExpression classReferenceExpression, object data) |
|
{ |
|
// VB's MyClass.Method references methods in the CURRENT class, ignoring overrides!!! |
|
// that is supported neither by C# nor Boo. |
|
// Most of the time, "Me"="self" should also do the job. |
|
AddWarning(classReferenceExpression, "Class reference is not supported, replaced with self reference."); |
|
return new B.SelfLiteralExpression(GetLexicalInfo(classReferenceExpression)); |
|
} |
|
|
|
B.BinaryOperatorType ConvertOperator(AssignmentOperatorType op, out bool isInPlace) |
|
{ |
|
isInPlace = true; |
|
switch (op) { |
|
case AssignmentOperatorType.Add: |
|
return B.BinaryOperatorType.InPlaceAddition; |
|
case AssignmentOperatorType.Assign: |
|
return B.BinaryOperatorType.Assign; |
|
case AssignmentOperatorType.BitwiseAnd: |
|
return B.BinaryOperatorType.InPlaceBitwiseAnd; |
|
case AssignmentOperatorType.BitwiseOr: |
|
return B.BinaryOperatorType.InPlaceBitwiseOr; |
|
case AssignmentOperatorType.ConcatString: |
|
return B.BinaryOperatorType.InPlaceAddition; |
|
case AssignmentOperatorType.Divide: |
|
return B.BinaryOperatorType.InPlaceDivision; |
|
case AssignmentOperatorType.DivideInteger: |
|
return B.BinaryOperatorType.InPlaceDivision; |
|
case AssignmentOperatorType.ExclusiveOr: |
|
return B.BinaryOperatorType.InPlaceExclusiveOr; |
|
case AssignmentOperatorType.Modulus: |
|
isInPlace = false; |
|
return B.BinaryOperatorType.Modulus; |
|
case AssignmentOperatorType.Multiply: |
|
return B.BinaryOperatorType.InPlaceMultiply; |
|
case AssignmentOperatorType.Power: |
|
isInPlace = false; |
|
return B.BinaryOperatorType.Exponentiation; |
|
case AssignmentOperatorType.ShiftLeft: |
|
return B.BinaryOperatorType.InPlaceShiftLeft; |
|
case AssignmentOperatorType.ShiftRight: |
|
return B.BinaryOperatorType.InPlaceShiftRight; |
|
case AssignmentOperatorType.Subtract: |
|
return B.BinaryOperatorType.InPlaceSubtraction; |
|
default: |
|
return B.BinaryOperatorType.None; |
|
} |
|
} |
|
|
|
public object Visit(AssignmentExpression assignmentExpression, object data) |
|
{ |
|
B.Expression left = ConvertExpression(assignmentExpression.Left); |
|
B.Expression right = ConvertExpression(assignmentExpression.Right); |
|
bool isInPlace; |
|
B.BinaryOperatorType op = ConvertOperator(assignmentExpression.Op, out isInPlace); |
|
if (op == B.BinaryOperatorType.None) { |
|
AddError(assignmentExpression, "Unknown operator."); |
|
return null; |
|
} |
|
if (!isInPlace) { |
|
// convert L <OP>= R to L = L OP R |
|
right = new B.BinaryExpression(GetLexicalInfo(assignmentExpression), op, left, right); |
|
op = B.BinaryOperatorType.Assign; |
|
} |
|
return new B.BinaryExpression(GetLexicalInfo(assignmentExpression), op, left, right); |
|
} |
|
|
|
B.BinaryOperatorType ConvertOperator(BinaryOperatorType op) |
|
{ |
|
switch (op) { |
|
case BinaryOperatorType.Add: |
|
return B.BinaryOperatorType.Addition; |
|
case BinaryOperatorType.BitwiseAnd: |
|
return B.BinaryOperatorType.BitwiseAnd; |
|
case BinaryOperatorType.BitwiseOr: |
|
return B.BinaryOperatorType.BitwiseOr; |
|
case BinaryOperatorType.Concat: |
|
return B.BinaryOperatorType.Addition; |
|
case BinaryOperatorType.Divide: |
|
return B.BinaryOperatorType.Division; |
|
case BinaryOperatorType.DivideInteger: |
|
return B.BinaryOperatorType.Division; |
|
case BinaryOperatorType.Equality: |
|
return B.BinaryOperatorType.Equality; |
|
case BinaryOperatorType.ExclusiveOr: |
|
return B.BinaryOperatorType.ExclusiveOr; |
|
case BinaryOperatorType.GreaterThan: |
|
return B.BinaryOperatorType.GreaterThan; |
|
case BinaryOperatorType.GreaterThanOrEqual: |
|
return B.BinaryOperatorType.GreaterThanOrEqual; |
|
case BinaryOperatorType.InEquality: |
|
return B.BinaryOperatorType.Inequality; |
|
case BinaryOperatorType.LessThan: |
|
return B.BinaryOperatorType.LessThan; |
|
case BinaryOperatorType.LessThanOrEqual: |
|
return B.BinaryOperatorType.LessThanOrEqual; |
|
case BinaryOperatorType.Like: |
|
return B.BinaryOperatorType.Match; |
|
case BinaryOperatorType.LogicalAnd: |
|
return B.BinaryOperatorType.And; |
|
case BinaryOperatorType.LogicalOr: |
|
return B.BinaryOperatorType.Or; |
|
case BinaryOperatorType.Modulus: |
|
return B.BinaryOperatorType.Modulus; |
|
case BinaryOperatorType.Multiply: |
|
return B.BinaryOperatorType.Multiply; |
|
case BinaryOperatorType.NullCoalescing: |
|
return B.BinaryOperatorType.Or; |
|
case BinaryOperatorType.Power: |
|
return B.BinaryOperatorType.Exponentiation; |
|
case BinaryOperatorType.ReferenceEquality: |
|
return B.BinaryOperatorType.ReferenceEquality; |
|
case BinaryOperatorType.ReferenceInequality: |
|
return B.BinaryOperatorType.ReferenceInequality; |
|
case BinaryOperatorType.ShiftLeft: |
|
return B.BinaryOperatorType.ShiftLeft; |
|
case BinaryOperatorType.ShiftRight: |
|
return B.BinaryOperatorType.ShiftRight; |
|
case BinaryOperatorType.Subtract: |
|
return B.BinaryOperatorType.Subtraction; |
|
default: |
|
return B.BinaryOperatorType.None; |
|
} |
|
} |
|
|
|
|
|
B.UnaryOperatorType ConvertOperator(UnaryOperatorType op) |
|
{ |
|
switch (op) { |
|
case UnaryOperatorType.BitNot: |
|
return B.UnaryOperatorType.OnesComplement; |
|
case UnaryOperatorType.Not: |
|
return B.UnaryOperatorType.LogicalNot; |
|
case UnaryOperatorType.Decrement: |
|
return B.UnaryOperatorType.Decrement; |
|
case UnaryOperatorType.Increment: |
|
return B.UnaryOperatorType.Increment; |
|
case UnaryOperatorType.Minus: |
|
return B.UnaryOperatorType.UnaryNegation; |
|
case UnaryOperatorType.PostDecrement: |
|
return B.UnaryOperatorType.PostDecrement; |
|
case UnaryOperatorType.PostIncrement: |
|
return B.UnaryOperatorType.PostIncrement; |
|
default: |
|
return B.UnaryOperatorType.None; |
|
} |
|
} |
|
|
|
public object Visit(BinaryOperatorExpression binaryOperatorExpression, object data) |
|
{ |
|
B.Expression left = ConvertExpression(binaryOperatorExpression.Left); |
|
B.Expression right = ConvertExpression(binaryOperatorExpression.Right); |
|
B.BinaryOperatorType op = ConvertOperator(binaryOperatorExpression.Op); |
|
if (op == B.BinaryOperatorType.None) { |
|
AddError(binaryOperatorExpression, "Unknown operator."); |
|
return null; |
|
} |
|
// if (binaryOperatorExpression.Op == BinaryOperatorType.DivideInteger) { |
|
// AddWarning(binaryOperatorExpression, "Integer division converted to normal division."); |
|
// } |
|
return new B.BinaryExpression(GetLexicalInfo(binaryOperatorExpression), op, left, right); |
|
} |
|
|
|
public object Visit(UnaryOperatorExpression unaryOperatorExpression, object data) |
|
{ |
|
B.Expression expr = ConvertExpression(unaryOperatorExpression.Expression); |
|
if (unaryOperatorExpression.Op == UnaryOperatorType.Plus) |
|
return expr; |
|
B.UnaryOperatorType op = ConvertOperator(unaryOperatorExpression.Op); |
|
if (op == B.UnaryOperatorType.None) { |
|
AddError(unaryOperatorExpression, "Unknown operator."); |
|
return null; |
|
} |
|
return new B.UnaryExpression(GetLexicalInfo(unaryOperatorExpression), op, expr); |
|
} |
|
|
|
public object Visit(ParenthesizedExpression parenthesizedExpression, object data) |
|
{ |
|
return ConvertExpression(parenthesizedExpression.Expression); |
|
} |
|
|
|
public object Visit(InvocationExpression ie, object data) |
|
{ |
|
if (ie.TypeArguments != null && ie.TypeArguments.Count > 0) { |
|
AddError(ie, "Generic method calls are not supported."); |
|
} |
|
B.Expression e = ConvertExpression(ie.TargetObject); |
|
if (e == null) |
|
return null; |
|
if (settings.IsVisualBasic && ie.TargetObject is IdentifierExpression && currentStatement != null) { |
|
VariableResolver resolver = new VariableResolver(nameComparer); |
|
TypeReference typeRef = resolver.FindType((ie.TargetObject as IdentifierExpression).Identifier, currentStatement); |
|
if (typeRef != null && typeRef.IsArrayType) { |
|
// Visual Basic: indexer expression |
|
B.SlicingExpression s = new B.SlicingExpression(GetLexicalInfo(ie)); |
|
s.Target = e; |
|
foreach (Expression expr in ie.Arguments) { |
|
s.Indices.Add(new B.Slice(ConvertExpression(expr))); |
|
} |
|
return s; |
|
} |
|
} |
|
B.MethodInvocationExpression r = new B.MethodInvocationExpression(GetLexicalInfo(ie), e); |
|
foreach (Expression expr in ie.Arguments) { |
|
e = ConvertExpression(expr); |
|
if (e != null) { |
|
r.Arguments.Add(e); |
|
} |
|
} |
|
return r; |
|
} |
|
|
|
public object Visit(ObjectCreateExpression objectCreateExpression, object data) |
|
{ |
|
TypeReference t = objectCreateExpression.CreateType; |
|
if (t.IsArrayType) { |
|
throw new ApplicationException("ObjectCreateExpression cannot be called with an ArrayType"); |
|
} |
|
// HACK: Tricking out event handlers |
|
if (t.SystemType.EndsWith("EventHandler") && objectCreateExpression.Parameters.Count == 1) |
|
return ConvertExpression((Expression)objectCreateExpression.Parameters[0]); |
|
|
|
B.MethodInvocationExpression mie = new B.MethodInvocationExpression(GetLexicalInfo(objectCreateExpression), MakeReferenceExpression(t)); |
|
ConvertExpressions(objectCreateExpression.Parameters, mie.Arguments); |
|
return mie; |
|
} |
|
|
|
public object Visit(TypeReferenceExpression typeReferenceExpression, object data) |
|
{ |
|
return MakeReferenceExpression(typeReferenceExpression.TypeReference); |
|
} |
|
|
|
public object Visit(SizeOfExpression sizeOfExpression, object data) |
|
{ |
|
AddError(sizeOfExpression, "sizeof is not supported."); |
|
return null; |
|
} |
|
|
|
public object Visit(DefaultValueExpression defaultValueExpression, object data) |
|
{ |
|
AddError(defaultValueExpression, "default() is not supported."); |
|
return null; |
|
} |
|
|
|
public object Visit(TypeOfExpression typeOfExpression, object data) |
|
{ |
|
return new B.TypeofExpression(GetLexicalInfo(typeOfExpression), ConvertTypeReference(typeOfExpression.TypeReference)); |
|
} |
|
|
|
public object Visit(TypeOfIsExpression typeOfIsExpression, object data) |
|
{ |
|
return new B.BinaryExpression(GetLexicalInfo(typeOfIsExpression), B.BinaryOperatorType.TypeTest, |
|
ConvertExpression(typeOfIsExpression.Expression), |
|
MakeReferenceExpression(typeOfIsExpression.TypeReference)); |
|
} |
|
|
|
public object Visit(AddressOfExpression addressOfExpression, object data) |
|
{ |
|
// Boo can reference methods directly |
|
return ConvertExpression(addressOfExpression.Expression); |
|
} |
|
|
|
public object Visit(PointerReferenceExpression pointerReferenceExpression, object data) |
|
{ |
|
AddError(pointerReferenceExpression, "Pointers are not supported."); |
|
return null; |
|
} |
|
|
|
public object Visit(CastExpression castExpression, object data) |
|
{ |
|
switch (castExpression.CastType) { |
|
case CastType.Cast: |
|
case CastType.Conversion: |
|
case CastType.PrimitiveConversion: |
|
return new B.CastExpression(GetLexicalInfo(castExpression), |
|
ConvertExpression(castExpression.Expression), |
|
ConvertTypeReference(castExpression.CastTo)); |
|
case CastType.TryCast: |
|
return new B.TryCastExpression(GetLexicalInfo(castExpression), |
|
ConvertExpression(castExpression.Expression), |
|
ConvertTypeReference(castExpression.CastTo)); |
|
default: |
|
AddError(castExpression, "Unknown cast: " + castExpression); |
|
return null; |
|
} |
|
} |
|
|
|
public object Visit(StackAllocExpression stackAllocExpression, object data) |
|
{ |
|
AddError(stackAllocExpression, "StackAlloc is not supported."); |
|
return null; |
|
} |
|
|
|
public object Visit(ThisReferenceExpression thisReferenceExpression, object data) |
|
{ |
|
return new B.SelfLiteralExpression(GetLexicalInfo(thisReferenceExpression)); |
|
} |
|
|
|
public object Visit(BaseReferenceExpression baseReferenceExpression, object data) |
|
{ |
|
return new B.SuperLiteralExpression(GetLexicalInfo(baseReferenceExpression)); |
|
} |
|
|
|
public object Visit(DirectionExpression directionExpression, object data) |
|
{ |
|
// boo does not need to specify the direction when calling out/ref methods |
|
return ConvertExpression(directionExpression.Expression); |
|
} |
|
|
|
public object Visit(ArrayCreateExpression arrayCreateExpression, object data) |
|
{ |
|
if (!arrayCreateExpression.ArrayInitializer.IsNull) { |
|
return arrayCreateExpression.ArrayInitializer.AcceptVisitor(this, data); |
|
} |
|
string builtInName = (arrayCreateExpression.Arguments.Count > 1) ? "matrix" : "array"; |
|
B.MethodInvocationExpression mie = new B.MethodInvocationExpression(GetLexicalInfo(arrayCreateExpression), |
|
MakeReferenceExpression(builtInName)); |
|
TypeReference elementType = arrayCreateExpression.CreateType.Clone(); |
|
int[] newRank = new int[elementType.RankSpecifier.Length - 1]; |
|
for (int i = 0; i < newRank.Length; i++) |
|
newRank[i] = elementType.RankSpecifier[i + 1]; |
|
elementType.RankSpecifier = newRank; |
|
mie.Arguments.Add(MakeReferenceExpression(elementType)); |
|
if (arrayCreateExpression.Arguments.Count == 1) { |
|
mie.Arguments.Add(ConvertExpression(arrayCreateExpression.Arguments[0])); |
|
} else { |
|
B.ArrayLiteralExpression dims = new B.ArrayLiteralExpression(GetLexicalInfo(arrayCreateExpression)); |
|
ConvertExpressions(arrayCreateExpression.Arguments, dims.Items); |
|
mie.Arguments.Add(dims); |
|
} |
|
return mie; |
|
} |
|
|
|
public object Visit(ArrayInitializerExpression aie, object data) |
|
{ |
|
B.ArrayLiteralExpression dims = new B.ArrayLiteralExpression(GetLexicalInfo(aie)); |
|
ConvertExpressions(aie.CreateExpressions, dims.Items); |
|
return dims; |
|
} |
|
|
|
public object Visit(IndexerExpression indexerExpression, object data) |
|
{ |
|
B.SlicingExpression s = new B.SlicingExpression(GetLexicalInfo(indexerExpression)); |
|
s.Target = ConvertExpression(indexerExpression.TargetObject); |
|
foreach (Expression expr in indexerExpression.Indices) { |
|
s.Indices.Add(new B.Slice(ConvertExpression(expr))); |
|
} |
|
return s; |
|
} |
|
|
|
public object Visit(AnonymousMethodExpression anonymousMethodExpression, object data) |
|
{ |
|
B.CallableBlockExpression cbe = new B.CallableBlockExpression(GetLexicalInfo(anonymousMethodExpression)); |
|
cbe.EndSourceLocation = GetLocation(anonymousMethodExpression.EndLocation); |
|
cbe.Body = ConvertBlock(anonymousMethodExpression.Body); |
|
ConvertParameters(anonymousMethodExpression.Parameters, cbe.Parameters); |
|
return cbe; |
|
} |
|
|
|
public object Visit(ConditionalExpression conditionalExpression, object data) |
|
{ |
|
B.TernaryExpression te = new B.TernaryExpression(GetLexicalInfo(conditionalExpression)); |
|
te.Condition = ConvertExpression(conditionalExpression.Condition); |
|
te.TrueValue = ConvertExpression(conditionalExpression.TrueExpression); |
|
te.FalseValue = ConvertExpression(conditionalExpression.FalseExpression); |
|
return te; |
|
} |
|
|
|
public object Visit(CheckedExpression checkedExpression, object data) |
|
{ |
|
AddError(checkedExpression, "Using 'checked' inside an expression is not supported by boo, " + |
|
"use the checked {} block instead."); |
|
return null; |
|
} |
|
|
|
public object Visit(UncheckedExpression uncheckedExpression, object data) |
|
{ |
|
AddError(uncheckedExpression, "Using 'unchecked' inside an expression is not supported by boo, " + |
|
"use the unchecked {} block instead."); |
|
return null; |
|
} |
|
} |
|
}
|
|
|