private static List <FieldDeclarationSyntax> SortFields(List <FieldDeclarationSyntax> fields) { if (fields.Count == 0) { return(fields); } var dependencies = fields.ToDictionary( o => TypeProcessor.GetDeclaredSymbol(o.Declaration.Variables.First()).As <IFieldSymbol>(), o => new { Syntax = o, Dependicies = new List <IFieldSymbol>() }); foreach (var dep in dependencies) { foreach ( var fieldDepend in dep.Value.Syntax.DescendantNodes() .OfType <ExpressionSyntax>() .Select(o => TypeProcessor.GetSymbolInfo(o).Symbol) .OfType <IFieldSymbol>()) { if (dependencies.ContainsKey(fieldDepend)) { dep.Value.Dependicies.Add(fieldDepend); } } } var ret = new List <FieldDeclarationSyntax>(); var symbolsAdded = new HashSet <IFieldSymbol>(); while (dependencies.Count > 0) { foreach (var dep in dependencies.ToList()) { for (int i = 0; i < dep.Value.Dependicies.Count; i++) { if (symbolsAdded.Contains(dep.Value.Dependicies[i])) { dep.Value.Dependicies.RemoveAt(i--); } } if (dep.Value.Dependicies.Count == 0) { ret.Add(dep.Value.Syntax); symbolsAdded.Add(dep.Key); dependencies.Remove(dep.Key); } } } return(ret); }
public void Write(OutputWriter writer) { if (StringOpt != null) { writer.Write(StringOpt); } else { if (ArgumentOpt.NameColon != null) { Core.Write(writer, ArgumentOpt.NameColon.Name); writer.Write(" = "); } var symbol = TypeProcessor.GetSymbolInfo(ArgumentOpt.Expression); var type = TypeProcessor.GetTypeInfo(ArgumentOpt.Expression); if (symbol.Symbol != null && type.ConvertedType != null && symbol.Symbol.Kind == SymbolKind.Method && type.ConvertedType.TypeKind == TypeKind.Delegate) { var typeString = TypeProcessor.ConvertType(type.ConvertedType); var createNew = !(ArgumentOpt.Parent.Parent is ObjectCreationExpressionSyntax); //Ugly hack if (createNew) { if (type.ConvertedType.TypeKind == TypeKind.TypeParameter) { writer.Write(" __TypeNew!(" + typeString + ")("); } else { writer.Write("new " + typeString + "("); } } var isStatic = symbol.Symbol.IsStatic; // if (isStatic) //Not Needed, delegate class now supports functions directly // writer.Write("__ToDelegate("); MemberUtilities.WriteMethodPointer(writer, ArgumentOpt.Expression); // if (isStatic) // writer.Write(")"); if (createNew) { writer.Write(")"); } return; } Core.Write(writer, ArgumentOpt.Expression); } }
/// <summary> /// Determines if the passed symbol is used in any ref or out clauses /// </summary> private static bool UsedAsRef(VariableDeclaratorSyntax variable, ISymbol symbol) { SyntaxNode node = variable; BlockSyntax scope; do { scope = (node = node.Parent) as BlockSyntax; }while (scope == null); return(scope.DescendantNodes().OfType <InvocationExpressionSyntax>() .SelectMany(o => o.ArgumentList.Arguments) .Where(o => o.RefOrOutKeyword.RawKind != (decimal)SyntaxKind.None) .Any(o => TypeProcessor.GetSymbolInfo(o.Expression).Symbol == symbol)); }
public static void WriteMember(OutputWriter writer, ExpressionSyntax expression) { var symbol = TypeProcessor.GetSymbolInfo(expression).Symbol; if (symbol is INamedTypeSymbol) { var str = TypeProcessor.ConvertType(symbol.As <INamedTypeSymbol>()); if (str == "Array_T") { // Array is the only special case, otherwise generics have to be specialized to access static members str = "Array"; } writer.Write(str); } else { Core.Write(writer, expression); } }
public static void WriteMethodPointer(OutputWriter writer, SyntaxNode expression) { writer.Write("&"); var symbol = TypeProcessor.GetSymbolInfo(expression).Symbol; // // else { Core.Write(writer, expression); if (symbol is IMethodSymbol && !(expression is GenericNameSyntax)) { //Type inference for delegates var methodSymbol = symbol as IMethodSymbol; // var methodName = TypeProcessor.ConvertType(methodSymbol.ContainingType) +"."+ WriteIdentifierName.TransformIdentifier(methodSymbol.Name); var specializedMethod = //methodName + (methodSymbol.TypeArguments.Any() ? ("!(" + methodSymbol.TypeArguments.Select(k => TypeProcessor.ConvertType(k)) .Aggregate((a, b) => a + "," + b) + ")") : ""); writer.Write(specializedMethod); } } }
public static string WriteMemberToString(ExpressionSyntax expression) { var result = ""; var symbol = TypeProcessor.GetSymbolInfo(expression).Symbol; if (symbol is INamedTypeSymbol) { var str = TypeProcessor.ConvertType(symbol.As <INamedTypeSymbol>()); if (str == "Array_T") { // Array is the only special case, otherwise generics have to be specialized to access static members str = "Array"; } result += (str); } else { result += Core.WriteString(expression); } return(result); }
public static void WritePrefix(OutputWriter writer, PrefixUnaryExpressionSyntax expression) { var isProperty = false; var symbol = TypeProcessor.GetSymbolInfo(expression.Operand); if (symbol.Symbol is IPropertySymbol) { isProperty = true; } if (isProperty) { var symbolName = Core.WriteString(expression.Operand).ToString().Trim(); switch (expression.OperatorToken.RawKind) { case (int)SyntaxKind.MinusMinusToken: if ((symbol.Symbol as IPropertySymbol).IsIndexer) { writer.Write(String.Format("/*--{0}*/((){{ auto v = {0};{0}=(--v);return v;}})()", symbolName)); } else { writer.Write(String.Format("/*--{0}*/((){{ auto v = {0};{0}(--v);return v;}})()", symbolName)); } break; case (int)SyntaxKind.PlusPlusToken: if ((symbol.Symbol as IPropertySymbol).IsIndexer) { writer.Write(String.Format("/*++{0}*/((){{ auto v = {0};{0}=(++v);return v;}})()", symbolName)); } else { writer.Write(String.Format("/*++{0}*/((){{ auto v = {0};{0}(++v);return v;}})()", symbolName)); } break; default: writer.Write(expression.OperatorToken.Text); Core.Write(writer, expression.Operand); break; } } else { // Console.WriteLine (expression.ToFullString()); // if (expression.OperatorToken.RawKind == (decimal)SyntaxKind.MinusMinusToken) // { // // writer.Write ("--"); // Core.Write (writer, expression.Operand); // } // else if (expression.OperatorToken.RawKind == (decimal)SyntaxKind.PlusPlusToken) // { // writer.Write ("++"); // Core.Write (writer, expression.Operand); // } // else // { // //TODO: cannot take addresses of structs in 32/64-bit mode and subtract them ... really weird d-bug ... leads to wrong math ... should we do a shift ? //// if (expression.OperatorToken.CSharpKind () == SyntaxKind.AmpersandToken) // Take address //// { //// var memberAccess = expression.Operand as MemberAccessExpressionSyntax; //// var simpleName = expression.Operand as NameSyntax; //// //// TypeInfo typeOperand; //// //// if (memberAccess != null) //// typeOperand = TypeProcessor.GetTypeInfo (memberAccess.Expression); //// if (simpleName != null) //// typeOperand = TypeProcessor.GetTypeInfo (simpleName); //// //// var failed = true; // //// if (memberAccess != null) //// { //// failed = false; //// if (typeOperand.Type.TypeKind == TypeKind.Struct) //// { //// var sNAme = (memberAccess.Expression as SimpleNameSyntax).Identifier; //// //// writer.Write ("(cast(ulong)(&" + sNAme.ToFullString () + ") + ("); //// Core.Write (writer, expression.Operand); //// writer.Write (".offsetof))"); //// } //// else //// failed = true; //// } //// else if (simpleName != null) //// { //// failed = false; //// //// if (typeOperand.Type.TypeKind == TypeKind.Struct) //// { //// writer.Write ("(&" + simpleName.ToFullString () + " + ("); //// Core.Write (writer, expression.Operand); //// writer.Write (".offsetof))"); //// } //// else //// failed = true; //// } //// //// if(failed) //// { //// writer.Write (expression.OperatorToken.ToString ()); //// Core.Write (writer, expression.Operand); //// } //// //// } //// else // { // writer.Write (expression.OperatorToken.ToString ()); // Core.Write (writer, expression.Operand); // } // } //D's unary operators are a bit different from C# .. i.e. not static bool hasOpIncrement = false; bool hasOpDecrement = false; var typeSymbol = TypeProcessor.GetTypeInfo(expression.Operand).Type; if (typeSymbol != null) { hasOpIncrement = typeSymbol.GetMembers("op_Increment").Any(); hasOpDecrement = typeSymbol.GetMembers("op_Decrement").Any(); } switch (expression.OperatorToken.RawKind) { case (int)SyntaxKind.MinusMinusToken: if (hasOpDecrement) { var texpression = Core.WriteString(expression.Operand); writer.Write(String.Format("/*--{0}*/((){{ auto v = {0};{0}={0}.op_Decrement({0});return v;}})()", texpression)); } else { writer.Write("--"); Core.Write(writer, expression.Operand); } break; case (int)SyntaxKind.PlusPlusToken: if (hasOpIncrement) { var texpression = Core.WriteString(expression.Operand); writer.Write(String.Format("/*++{0}*/((){{ auto v = {0};{0}={0}.op_Increment({0});return v;}})()", texpression)); } else { writer.Write("++"); Core.Write(writer, expression.Operand); } break; default: writer.Write(expression.OperatorToken.Text); Core.Write(writer, expression.Operand); // throw new Exception("No support for " + expression.OperatorToken.RawKind + " at " + //Utility.Descriptor(expression)); break; } } }
public static void WritePostfix(OutputWriter writer, PostfixUnaryExpressionSyntax expression) { var isProperty = false; var symbol = TypeProcessor.GetSymbolInfo(expression.Operand); if (symbol.Symbol is IPropertySymbol) { isProperty = true; } if (isProperty) { var symbolName = Core.WriteString(expression.Operand); switch (expression.OperatorToken.RawKind) { case (int)SyntaxKind.MinusMinusToken: if ((symbol.Symbol as IPropertySymbol).IsIndexer) { writer.Write(String.Format("/*{0}--*/((){{auto v={0};auto y=v;{0}=(--y);return v;}})()", symbolName)); } else { writer.Write(String.Format("/*{0}--*/((){{auto v={0};auto y=v;{0}(--y);return v;}})()", symbolName)); } break; case (int)SyntaxKind.PlusPlusToken: if ((symbol.Symbol as IPropertySymbol).IsIndexer) { writer.Write(String.Format("/*{0}++*/((){{auto v={0},y={0};{0}=(++y);return v;}})()", symbolName)); } else { writer.Write(String.Format("/*{0}++*/((){{auto v={0},y={0};{0}(++y);return v;}})()", symbolName)); } break; default: Core.Write(writer, expression.Operand); writer.Write(expression.OperatorToken.Text); break; } } else { // if (expression.Operand is MemberAccessExpressionSyntax) // { // var memberAccess = expression.Operand as MemberAccessExpressionSyntax; // var typeInfo = TypeProcessor.GetSymbolInfo(memberAccess.Name); // if (typeInfo.Symbol.Kind == SymbolKind.Property) // { // switch (expression.OperatorToken.RawKind) // { // case (int)SyntaxKind.MinusMinusToken: // var refactored= SyntaxFactory.BinaryExpression(SyntaxKind.SimpleAssignmentExpression, // expression.Operand, // SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression, expression.Operand, // SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression,SyntaxFactory.Literal(-1))) // ).NormalizeWhitespace(); // Core.Write(writer,refactored); // break; // case (int)SyntaxKind.PlusPlusToken: // var refactored1 = SyntaxFactory.BinaryExpression(SyntaxKind.SimpleAssignmentExpression, // expression.Operand, // SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression, expression.Operand, // SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(+1))) // ).NormalizeWhitespace(); // Core.Write(writer, refactored1); // break; // default: // throw new Exception("No support for " + expression.OperatorToken.RawKind + " at " + // Utility.Descriptor(expression)); // } // } // else // { // switch (expression.OperatorToken.RawKind) // { // case (int)SyntaxKind.MinusMinusToken: // Core.Write(writer, expression.Operand); // writer.Write("--"); // break; // case (int)SyntaxKind.PlusPlusToken: // Core.Write(writer, expression.Operand); // writer.Write("++"); // break; // default: // throw new Exception("No support for " + expression.OperatorToken.RawKind + " at " + // Utility.Descriptor(expression)); // } // } // // } // else // { //D's unary operators are a bit different from C# .. i.e. not static bool hasOpIncrement = false; bool hasOpDecrement = false; var typeSymbol = TypeProcessor.GetTypeInfo(expression.Operand).Type; if (typeSymbol != null) { hasOpIncrement = typeSymbol.GetMembers("op_Increment").Any(); hasOpDecrement = typeSymbol.GetMembers("op_Decrement").Any(); } switch (expression.OperatorToken.RawKind) { case (int)SyntaxKind.MinusMinusToken: if (hasOpDecrement) { var texpression = Core.WriteString(expression.Operand); writer.Write(String.Format("/*{0}--*/({0}={0}.op_Decrement({0}))", texpression)); } else { Core.Write(writer, expression.Operand); writer.Write("--"); } break; case (int)SyntaxKind.PlusPlusToken: if (hasOpIncrement) { var texpression = Core.WriteString(expression.Operand); writer.Write(String.Format("/*{0}--*/({0}={0}.op_Increment({0}))", texpression)); } else { Core.Write(writer, expression.Operand); writer.Write("++"); } break; default: throw new Exception("No support for " + expression.OperatorToken.RawKind + " at " + Utility.Descriptor(expression)); } } // } }
private static void ProcessInitializer(OutputWriter writer, LocalDeclarationStatementSyntax declaration, VariableDeclaratorSyntax variable) { var initializer = variable.Initializer; if (initializer != null) { if (initializer.Value.CSharpKind() == SyntaxKind.CollectionInitializerExpression) { return; } var value = initializer.Value; var initializerType = TypeProcessor.GetTypeInfo(value); var memberaccessexpression = value as MemberAccessExpressionSyntax; var nameexpression = value as NameSyntax; var nullAssignment = value.ToFullString().Trim() == "null"; var shouldBox = initializerType.Type != null && initializerType.Type.IsValueType && !initializerType.ConvertedType.IsValueType; var shouldUnBox = initializerType.Type != null && !initializerType.Type.IsValueType && initializerType.ConvertedType.IsValueType; var isname = value is NameSyntax; var ismemberexpression = value is MemberAccessExpressionSyntax || (isname && TypeProcessor.GetSymbolInfo(value as NameSyntax).Symbol.Kind == SymbolKind.Method); var isdelegateassignment = ismemberexpression && initializerType.ConvertedType.TypeKind == TypeKind.Delegate; var isstaticdelegate = isdelegateassignment && ((memberaccessexpression != null && TypeProcessor.GetSymbolInfo(memberaccessexpression).Symbol.IsStatic) || (isname && TypeProcessor.GetSymbolInfo(nameexpression).Symbol.IsStatic)); //Do we have an implicit converter, if so, use it if (shouldBox || shouldUnBox) { // if (shouldUnBox) // { // bool useType = true; // // //We should start with exact converters and then move to more generic convertors i.e. base class or integers which are implicitly convertible // var correctConverter = initializerType.Type.GetImplicitCoversionOp(initializerType.Type,initializerType.ConvertedType); //// initializerType.Type.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); // // if (correctConverter == null) // { // useType = false; // correctConverter = // initializerType.ConvertedType.GetImplicitCoversionOp(initializerType.Type, initializerType.ConvertedType); //.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); // } // // if (correctConverter != null) // { // if(useType) // writer.Write(TypeProcessor.ConvertType(initializerType.Type) +"."+ "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType)); // else // { // writer.Write(TypeProcessor.ConvertType(initializerType.ConvertedType) +"."+ "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType)); // // } // writer.Write("("); // Core.Write(writer, value); // writer.Write(")"); // return; // } // } // if (shouldBox) { bool useType = true; var correctConverter = initializerType.Type.GetImplicitCoversionOp(initializerType.ConvertedType, initializerType.Type); //.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.ConvertedType && h.Parameters[0].Type == initializerType.Type); if (correctConverter == null) { useType = false; correctConverter = initializerType.ConvertedType.GetImplicitCoversionOp(initializerType.ConvertedType, initializerType.Type); //.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.ConvertedType && h.Parameters[0].Type == initializerType.Type); } if (correctConverter != null) { if (useType) { writer.Write(TypeProcessor.ConvertType(initializerType.Type) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType)); } else { writer.Write(TypeProcessor.ConvertType(initializerType.ConvertedType) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType)); } writer.Write("("); Core.Write(writer, value); writer.Write(")"); return; } } } if (nullAssignment) { writer.Write("null"); return; } if (shouldBox) { //Box writer.Write("BOX!(" + TypeProcessor.ConvertType(initializerType.Type) + ")("); //When passing an argument by ref or out, leave off the .Value suffix Core.Write(writer, value); writer.Write(")"); return; } if (shouldUnBox) { //UnBox writer.Write("cast!(" + TypeProcessor.ConvertType(initializerType.Type) + ")("); Core.Write(writer, value); writer.Write(")"); } if (isdelegateassignment) { var createNew = !(value is ObjectCreationExpressionSyntax); var typeString = TypeProcessor.ConvertType(initializerType.ConvertedType); if (createNew) { if (initializerType.ConvertedType.TypeKind == TypeKind.TypeParameter) { writer.Write(" __TypeNew!(" + typeString + ")("); } else { writer.Write("new " + typeString + "("); } } var isStatic = isstaticdelegate; if (isStatic) { writer.Write("__ToDelegate("); } writer.Write("&"); Core.Write(writer, value); if (isStatic) { writer.Write(")"); } if (createNew) { writer.Write(")"); } return; } if (initializerType.Type == null && initializerType.ConvertedType == null) { writer.Write("null"); return; } Core.Write(writer, value); } else { writer.Write(TypeProcessor.DefaultValue(declaration.Declaration.Type)); } }
public static void Go(OutputWriter writer, CastExpressionSyntax expression) { var symbol = TypeProcessor.GetSymbolInfo(expression); var castingFrom = TypeProcessor.GetTypeInfo(expression.Expression).Type ?? TypeProcessor.GetTypeInfo(expression).Type; var srcTypeDlang = TypeProcessor.ConvertType(castingFrom); var destType = TypeProcessor.GetTypeInfo(expression.Type).Type; var destTypeDlang = TypeProcessor.TryConvertType(expression.Type); if (destTypeDlang == srcTypeDlang) { Core.Write(writer, expression.Expression); } else //if (symbol.Symbol != null)// && srcTypeCpp != "int" && srcTypeCpp != "System.String" && srcTypeCpp != "bool") { // if (castingFrom != destType) // Check for implicit first then explicit bool useType = true; //We should start with exact converters and then move to more generic convertors i.e. base class or integers which are implicitly convertible var correctConverter = destType.GetImplicitCoversionOp(destType, castingFrom, true); // initializerType.Type.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); if (correctConverter == null) { useType = false; correctConverter = castingFrom.GetImplicitCoversionOp(destType, castingFrom, true); //.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); } if (correctConverter != null) { // Core.Write(writer, expression.Left); // writer.Write(" = "); if (correctConverter.ReturnType != destType) { writer.Write("Cast!(" + destTypeDlang + (destType.IsValueType ? "" : "") + ")("); } if (castingFrom.SpecialType == SpecialType.System_Decimal && destType.IsPrimitiveInteger()) { } else { if (useType) { writer.Write(TypeProcessor.ConvertType(destType) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } else { writer.Write(TypeProcessor.ConvertType(castingFrom) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } } writer.Write("("); Core.Write(writer, expression.Expression); writer.Write(")"); if (correctConverter.ReturnType != destType) { writer.Write(")"); } return; } useType = true; //We should start with exact converters and then move to more generic convertors i.e. base class or integers which are implicitly convertible correctConverter = destType.GetExplictCoversionOp(destType, castingFrom, true); // initializerType.Type.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); if (correctConverter == null) { useType = false; correctConverter = castingFrom.GetExplictCoversionOp(destType, castingFrom, true); //.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); } if (correctConverter != null) { var iscast = correctConverter.ReturnType != destType; if (iscast) { writer.Write("Cast!(" + destTypeDlang + ")("); } // Core.Write(writer, expression.Left); // writer.Write(" = "); if (castingFrom.SpecialType == SpecialType.System_Decimal && destType.IsPrimitiveInteger()) { } else { if (useType) { writer.Write(TypeProcessor.ConvertType(destType) + "." + "op_Explicit"); } else { writer.Write(TypeProcessor.ConvertType(castingFrom) + "." + "op_Explicit"); } } writer.Write("("); Core.Write(writer, expression.Expression); writer.Write(")"); if (iscast) { writer.Write(")"); } return; } if (TypeProcessor.IsPrimitiveType(srcTypeDlang) && TypeProcessor.IsPrimitiveType(destTypeDlang)) {//primitives can be directly cast writer.Write("cast(" + destTypeDlang + ")"); Core.Write(writer, expression.Expression); } else { var convertedType = TypeProcessor.GetTypeInfo(expression).Type; var type = TypeProcessor.GetTypeInfo(expression.Expression).Type; if (type.IsValueType && !convertedType.IsValueType) { //We have to box then cast if not Object if (destType.Name != "Object") { writer.Write("Cast!(" + destTypeDlang + ")("); } //Box writer.Write("BOX!(" + TypeProcessor.ConvertType(type) + ")("); //When passing an argument by ref or out, leave off the .Value suffix // writer.Write(" >("); Core.Write(writer, expression.Expression); writer.Write(")"); if (destType.Name != "Object") { writer.Write(")"); } } else if (!type.IsValueType && convertedType.IsValueType) { //UnBox // writer.Write("(Cast!( Boxed!(" + TypeProcessor.ConvertType(convertedType) + ") )("); // Core.Write(writer, expression.Expression); // writer.Write(")).Value"); writer.Write("UNBOX!(" + TypeProcessor.ConvertType(convertedType) + ")("); Core.Write(writer, expression.Expression); writer.Write(")"); } else if (type.IsValueType && convertedType.IsValueType) { if (convertedType.TypeKind == TypeKind.Pointer) { //cannot use ascast here, its for boxed types and objects writer.Write("cast(" + destTypeDlang + (destType.IsValueType ? "" : "") + ")("); Core.Write(writer, expression.Expression); writer.Write(")"); } else { //cannot use ascast here, its for boxed types and objects writer.Write("Cast!(" + destTypeDlang + (destType.IsValueType ? "" : "") + ")("); Core.Write(writer, expression.Expression); writer.Write(")"); } } else { writer.Write("Cast!("); writer.Write(destTypeDlang); writer.Write(")("); Core.Write(writer, expression.Expression); writer.Write(")"); } } } }
private static void ProcessArgument(OutputWriter writer, ArgumentSyntax variable, bool isOverloaded = false) { if (variable != null) { if (variable.NameColon != null) { } if (CSharpExtensions.CSharpKind(variable) == SyntaxKind.CollectionInitializerExpression) { return; } var value = variable; var initializerType = TypeProcessor.GetTypeInfo(value.Expression); var memberaccessexpression = value.Expression as MemberAccessExpressionSyntax; var nameexpression = value.Expression as NameSyntax; var nullAssignment = value.ToFullString().Trim() == "null"; var shouldBox = initializerType.Type != null && (initializerType.Type != initializerType.ConvertedType) && ((initializerType.Type.IsValueType || initializerType.Type.TypeKind == TypeKind.TypeParameter) && (!initializerType.ConvertedType.IsValueType)); var shouldCast = initializerType.Type != null && (initializerType.Type.TypeKind == TypeKind.Interface && initializerType.ConvertedType.SpecialType == SpecialType.System_Object); var shouldUnBox = initializerType.Type != null && (initializerType.Type != initializerType.ConvertedType) && !initializerType.Type.IsValueType && initializerType.ConvertedType.IsValueType; var isname = value.Expression is NameSyntax; var ismemberexpression = value.Expression is MemberAccessExpressionSyntax || (isname && TypeProcessor.GetSymbolInfo(value.Expression as NameSyntax).Symbol.Kind == SymbolKind.Method); var isdelegateassignment = ismemberexpression && initializerType.ConvertedType != null && initializerType.ConvertedType.TypeKind == TypeKind.Delegate; var isstaticdelegate = isdelegateassignment && ((memberaccessexpression != null && TypeProcessor.GetSymbolInfo(memberaccessexpression).Symbol.IsStatic) || (isname && TypeProcessor.GetSymbolInfo(nameexpression).Symbol.IsStatic)); if (isOverloaded) { writer.Write("cast(const({0}))", TypeProcessor.ConvertType(initializerType.Type)); } if (shouldCast) { writer.Write("cast(NObject)"); writer.Write("("); Core.Write(writer, value.Expression); writer.Write(")"); return; } if (nullAssignment) { writer.Write("null"); return; } if (shouldBox) { bool useType = true; //We should start with exact converters and then move to more generic convertors i.e. base class or integers which are implicitly convertible var correctConverter = initializerType.Type.GetImplicitCoversionOp(initializerType.ConvertedType, initializerType.Type, true); // initializerType.Type.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); if (correctConverter == null) { useType = false; correctConverter = initializerType.ConvertedType.GetImplicitCoversionOp(initializerType.ConvertedType, initializerType.Type, true); //.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); } if (correctConverter != null) { if (useType) { writer.Write(TypeProcessor.ConvertType(initializerType.Type) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } else { writer.Write(TypeProcessor.ConvertType(initializerType.ConvertedType) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } writer.Write("("); Core.Write(writer, value.Expression); writer.Write(")"); return; } } else if (shouldUnBox) { bool useType = true; //We should start with exact converters and then move to more generic convertors i.e. base class or integers which are implicitly convertible var correctConverter = initializerType.Type.GetImplicitCoversionOp(initializerType.Type, initializerType.ConvertedType, true); // initializerType.Type.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); if (correctConverter == null) { useType = false; correctConverter = initializerType.ConvertedType.GetImplicitCoversionOp(initializerType.Type, initializerType.ConvertedType, true); //.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); } if (correctConverter != null) { if (useType) { writer.Write(TypeProcessor.ConvertType(initializerType.Type) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } else { writer.Write(TypeProcessor.ConvertType(initializerType.ConvertedType) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } writer.Write("("); Core.Write(writer, value.Expression); writer.Write(")"); return; } } if (shouldBox) { //Box writer.Write("BOX!(" + TypeProcessor.ConvertType(initializerType.Type) + ")("); //When passing an argument by ref or out, leave off the .Value suffix Core.Write(writer, value.Expression); writer.Write(")"); return; } if (shouldUnBox) { //UnBox writer.Write("Cast!(" + TypeProcessor.ConvertType(initializerType.Type) + ")("); Core.Write(writer, value.Expression); writer.Write(")"); } if (isdelegateassignment) { var typeString = TypeProcessor.ConvertType(initializerType.ConvertedType); var createNew = !(value.Expression is ObjectCreationExpressionSyntax); if (createNew) { if (initializerType.ConvertedType.TypeKind == TypeKind.TypeParameter) { writer.Write(" __TypeNew!(" + typeString + ")("); } else { writer.Write("new " + typeString + "("); } } var isStatic = isstaticdelegate; // if (isStatic) // writer.Write("__ToDelegate("); MemberUtilities.WriteMethodPointer(writer, value.Expression); // if (isStatic) // writer.Write(")"); if (createNew) { writer.Write(")"); } return; } if (initializerType.Type == null && initializerType.ConvertedType == null) { writer.Write("null"); return; } Core.Write(writer, value.Expression); } }
public static void Go(OutputWriter writer, InvocationExpressionSyntax invocationExpression) { var symbolInfo = TypeProcessor.GetSymbolInfo(invocationExpression); var expressionSymbol = TypeProcessor.GetSymbolInfo(invocationExpression.Expression); var symbol = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault(); // Resolution error if (symbol == null) { writer.WriteLine("/*" + invocationExpression.ToFullString() + " //SharpNative Failed To Get Symbol */"); } var methodSymbol = symbol.OriginalDefinition.As <IMethodSymbol>().UnReduce(); var memberReferenceExpressionOpt = invocationExpression.Expression as MemberAccessExpressionSyntax; var firstParameter = true; var extensionNamespace = methodSymbol.IsExtensionMethod ? methodSymbol.ContainingNamespace.FullNameWithDot() + methodSymbol.ContainingType.FullName() : null; //null means it's not an extension method, non-null means it is string methodName; string typeParameters = null; ExpressionSyntax subExpressionOpt; if (expressionSymbol.Symbol is IEventSymbol) { methodName = "Invoke"; } else if (methodSymbol.MethodKind == MethodKind.DelegateInvoke) { methodName = null; } else { methodName = OverloadResolver.MethodName(methodSymbol); } if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface || Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol)) { /* methodName = * Regex.Replace(TypeProcessor.ConvertType(methodSymbol.ContainingType.OriginalDefinition) * .RemoveFromStartOfString(methodSymbol.ContainingNamespace + ".Namespace.") + "_" + * methodName, * @" ?!\(.*?\)", string.Empty);*/ if (methodSymbol.ContainingType.ContainingType != null) { methodName = methodName.RemoveFromStartOfString(methodSymbol.ContainingType.ContainingType.Name + "."); } } var interfaceMethods = methodSymbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(methodName)).ToArray(); ISymbol interfaceMethod = interfaceMethods.FirstOrDefault( o => methodSymbol.ContainingType.FindImplementationForInterfaceMember(o) == methodSymbol); // if (interfaceMethod == null) // { // //TODO: fix this for virtual method test 7, seems roslyn cannot deal with virtual // // overrides of interface methods ... so i'll provide a kludge // if (!method.Modifiers.Any(SyntaxKind.NewKeyword)) // interfaceMethod = interfaceMethods.FirstOrDefault(k => CompareMethods(k as IMethodSymbol, methodSymbol)); // } if (interfaceMethod != null) // && CompareMethods(interfaceMethod ,methodSymbol)) { { //This is an interface method //TO if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array) { writer.Write(""); } else { /* var typenameI = * Regex.Replace( * TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom, true), * @" ?!\(.*?\)", string.Empty); * //TODO: we should be able to get the original interface name, or just remove all generics from this * if (typenameI.Contains('.')) * typenameI = typenameI.SubstringAfterLast('.'); * writer.Write(typenameI + "_");*/ } } var containingType = interfaceMethod == null ? methodSymbol.ContainingType : interfaceMethod.ContainingType; bool isVirtualGeneric = methodSymbol.IsGenericMethod && (methodSymbol.IsVirtual || methodSymbol.ContainingType.TypeKind == TypeKind.Interface) && !containingType.IsAssignableFrom(Context.Instance.Type); // !(invocationExpression.Expression is BaseExpressionSyntax); if (isVirtualGeneric) { methodName = TypeProcessor.ConvertType(containingType, false, false, false).Replace(".", "_") + "_" + methodName; } if (methodSymbol.MethodKind == MethodKind.DelegateInvoke) { subExpressionOpt = invocationExpression.Expression; } else if (memberReferenceExpressionOpt != null) { if (memberReferenceExpressionOpt.Expression is PredefinedTypeSyntax) { subExpressionOpt = null; } else { subExpressionOpt = memberReferenceExpressionOpt.Expression; } } else { subExpressionOpt = null; } //When the code specifically names generic arguments, include them in the method name ... dmd needs help with inference, so we give it the types anyway if (methodSymbol.IsGenericMethod) { //return TryConvertType(named) + (named.TypeKind == TypeKind.Struct && o.ConstraintTypes.Any(k => k.TypeKind == //TypeKind.Interface) ? ".__Boxed_" : ""); var named = ((IMethodSymbol)symbol); typeParameters = "!(" + named.TypeArguments.Select(o => TypeProcessor.GetGenericParameterType(named.TypeParameters[named.TypeArguments.IndexOf(o)], o)).Aggregate((a, b) => a + ", " + b) + ")"; // typeParameters = "!( " + // string.Join(", ", // ((IMethodSymbol) symbol).TypeArguments.Select(r => TypeProcessor.ConvertType(r) )) + // " )"; } //Determine if it's an extension method called in a non-extension way. In this case, just pretend it's not an extension method if (extensionNamespace != null && subExpressionOpt != null && TypeProcessor.GetTypeInfo(subExpressionOpt).ConvertedType.ToString() == methodSymbol.ContainingNamespace.FullName() + "." + methodSymbol.ContainingType.FullName()) { extensionNamespace = null; } var memberType = memberReferenceExpressionOpt == null ? null : TypeProcessor.GetTypeInfo(memberReferenceExpressionOpt.Expression).Type; var isNullableEnum = memberType != null && (memberType.Name == "Nullable" && memberType.ContainingNamespace.FullName() == "System") && memberType.As <INamedTypeSymbol>().TypeArguments.Single().TypeKind == TypeKind.Enum; // if (isNullableEnum && methodSymbol.Name == "ToString") // { // extensionNamespace = null; //override Translations.xml for nullable enums. We want them to convert to the enum's ToString method // methodName = "toString"; // } //Invocation on basics should come from boxing the basic then calling on the boxed type, unless static var directInvocationOnBasics = methodSymbol.ContainingType.IsBasicType() && methodSymbol.IsStatic; //&& methodSymbol.ContainingType!=Context.Instance.Type; //If we are currently working on a basic type e.g. in corlib, don't alter the code //Extension methods in Dlang are straightforward, although this could lead to clashes without qualification string instanceName = null; if (extensionNamespace != null || directInvocationOnBasics) { if (extensionNamespace == null) { extensionNamespace = TypeProcessor.ConvertType(methodSymbol.ContainingType, true, false); // methodSymbol.ContainingNamespace.FullName() + "." + methodSymbol.ContainingType.Name; //memberType.ContainingNamespace.FullName() +"."+ memberType.Name; } if (!isVirtualGeneric) { writer.Write(extensionNamespace); if (methodName != null) { methodName = WriteIdentifierName.TransformIdentifier(methodName); // if (symbolInfo.Symbol.ContainingType != Context.Instance.Type) writer.Write("."); writer.Write(methodName); } } else { writer.Write(methodName); } WriteTypeParameters(writer, typeParameters, invocationExpression); writer.Write("("); if (subExpressionOpt != null) { firstParameter = false; Core.Write(writer, subExpressionOpt); } } else { if (memberReferenceExpressionOpt != null) { } if (subExpressionOpt != null) { if (!isVirtualGeneric) { WriteMemberAccessExpression.WriteMember(writer, subExpressionOpt); // if (!(subExpressionOpt is BaseExpressionSyntax)) // { // if (methodName != null && methodSymbol.IsStatic) // writer.Write("."); // else // { if (methodSymbol.MethodKind != MethodKind.DelegateInvoke) { writer.Write("."); } } else { instanceName = WriteMemberAccessExpression.WriteMemberToString(subExpressionOpt); } // } // } // writer.Write("."); } else if (methodSymbol.IsStatic && extensionNamespace == null) { if (methodSymbol.ContainingType != Context.Instance.Type) { var str = TypeProcessor.ConvertType(methodSymbol.ContainingType); if (str == "Array_T") { // Array is the only special case, otherwise generics have to be specialized to access static members str = "Array"; } writer.Write(str); // writer.Write(methodSymbol.ContainingNamespace.FullNameWithDot()); // writer.Write(WriteType.TypeName(methodSymbol.ContainingType)); writer.Write("."); } } if (methodSymbol.MethodKind != MethodKind.DelegateInvoke) { var declaringSyntaxReferences = methodSymbol.DeclaringSyntaxReferences.Select(j => j.GetSyntax()) .OfType <MethodDeclarationSyntax>(); var methodDeclarationSyntaxs = declaringSyntaxReferences as MethodDeclarationSyntax[] ?? declaringSyntaxReferences.ToArray(); var any = methodDeclarationSyntaxs.Any(); if (any && methodDeclarationSyntaxs.FirstOrDefault() .As <MethodDeclarationSyntax>() .Modifiers.Any(SyntaxKind.NewKeyword)) { //TODO: this means that new is not supported on external libraries // //why doesnt roslyn give me this information ? //methodName += "_"; //Not needed anymore :) } if (any && methodDeclarationSyntaxs.FirstOrDefault() .As <MethodDeclarationSyntax>() .Modifiers.Any(SyntaxKind.NewKeyword)) { // if (symbolInfo.Symbol.ContainingType != Context.Instance.Type) writer.Write(WriteIdentifierName.TransformIdentifier(methodSymbol.ContainingType.Name, methodSymbol.ContainingType) + "."); } methodName = WriteIdentifierName.TransformIdentifier(methodName); writer.Write(methodName); } WriteTypeParameters(writer, typeParameters, invocationExpression); writer.Write("("); } bool inParams = false; bool foundParamsArray = false; var arguments = invocationExpression.ArgumentList.Arguments; ITypeSymbol typeSymbol = null; bool isOverloaded = methodSymbol.ContainingType.GetMembers(methodSymbol.Name).OfType <IMethodSymbol>().Any(j => j.TypeParameters == methodSymbol.TypeParameters && ParameterMatchesWithRefOutIn(methodSymbol, j)); WriteArguments(writer, invocationExpression, arguments, firstParameter, inParams, methodSymbol, foundParamsArray, typeSymbol, isOverloaded, symbol, instanceName); }
public static void Go(OutputWriter writer, InvocationExpressionSyntax invocationExpression) { var symbolInfo = TypeProcessor.GetSymbolInfo(invocationExpression); var expressionSymbol = TypeProcessor.GetSymbolInfo(invocationExpression.Expression); var symbol = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault(); // Resolution error var methodSymbol = symbol.OriginalDefinition.As <IMethodSymbol>().UnReduce(); var memberReferenceExpressionOpt = invocationExpression.Expression as MemberAccessExpressionSyntax; var firstParameter = true; var extensionNamespace = methodSymbol.IsExtensionMethod ? methodSymbol.ContainingNamespace.FullNameWithDot() + methodSymbol.ContainingType.FullName() : null; //null means it's not an extension method, non-null means it is string methodName; string typeParameters = null; ExpressionSyntax subExpressionOpt; if (methodSymbol.ContainingType.FullName() == "Enum") { if (methodSymbol.Name == "Parse") { WriteEnumParse(writer, invocationExpression); return; } if (methodSymbol.Name == "GetValues") { WriteEnumGetValues(writer, invocationExpression); return; } } if (expressionSymbol.Symbol is IEventSymbol) { methodName = "Invoke"; //Would need to append the number of arguments to this to support events. However, events are not currently supported } // else if (memberReferenceExpressionOpt != null && memberReferenceExpressionOpt.Expression is PredefinedTypeSyntax) // { // switch (methodSymbol.Name) // { // case "Parse": // Core.Write(writer, invocationExpression.ArgumentList.Arguments.Single().Expression); // // writer.Write(".to"); // writer.Write(TypeProcessor.ConvertType(methodSymbol.ReturnType)); // // return; // case "TryParse": // methodName = "TryParse" + TypeProcessor.ConvertType(methodSymbol.Parameters[1].Type); // extensionNamespace = "SharpNative"; // break; // default: // methodName = methodSymbol.Name; // extensionNamespace = "SharpNative"; // break; // } // } else if (methodSymbol.MethodKind == MethodKind.DelegateInvoke) { methodName = null; } else { methodName = OverloadResolver.MethodName(methodSymbol); } if (methodSymbol.MethodKind == MethodKind.DelegateInvoke) { subExpressionOpt = invocationExpression.Expression; } else if (memberReferenceExpressionOpt != null) { if (memberReferenceExpressionOpt.Expression is PredefinedTypeSyntax) { subExpressionOpt = null; } else { subExpressionOpt = memberReferenceExpressionOpt.Expression; } } else { subExpressionOpt = null; } //When the code specifically names generic arguments, include them in the method name ... dlang needs help with inference, so we give it the types anyway if (methodSymbol.IsGenericMethod) { // var genNameExpression = invocationExpression.Expression as GenericNameSyntax; // if (genNameExpression == null && memberReferenceExpressionOpt != null) // genNameExpression = memberReferenceExpressionOpt.Name as GenericNameSyntax; // if (genNameExpression != null && genNameExpression.TypeArgumentList.Arguments.Count > 0) typeParameters = "!( " + string.Join(", ", (symbol as IMethodSymbol).TypeArguments.Select(r => TypeProcessor.ConvertType(r))) + " )"; } //Determine if it's an extension method called in a non-extension way. In this case, just pretend it's not an extension method if (extensionNamespace != null && subExpressionOpt != null && TypeProcessor.GetTypeInfo(subExpressionOpt).ConvertedType.ToString() == methodSymbol.ContainingNamespace + "." + methodSymbol.ContainingType.FullName()) { extensionNamespace = null; } var memberType = memberReferenceExpressionOpt == null ? null : TypeProcessor.GetTypeInfo(memberReferenceExpressionOpt.Expression).Type; var isNullableEnum = memberType != null && (memberType.Name == "Nullable" && memberType.ContainingNamespace.FullName() == "System") && memberType.As <INamedTypeSymbol>().TypeArguments.Single().TypeKind == TypeKind.Enum; // if (isNullableEnum && methodSymbol.Name == "ToString") // { // extensionNamespace = null; //override Translations.xml for nullable enums. We want them to convert to the enum's ToString method // methodName = "toString"; // } var directInvocationOnBasics = methodSymbol.ContainingType.IsBasicType(); //Extension methods in Dlang are straightforward, although this could lead to clashes without qualification if (extensionNamespace != null || directInvocationOnBasics) { if (extensionNamespace == null) { extensionNamespace = memberType.ContainingNamespace.FullName() + "." + memberType.Name; //memberType.ContainingNamespace.FullName() +"."+ memberType.Name; } writer.Write(extensionNamespace); if (methodName != null) { writer.Write("."); writer.Write(methodName); } WriteTypeParameters(writer, typeParameters, invocationExpression); writer.Write("("); if (subExpressionOpt != null) { firstParameter = false; Core.Write(writer, subExpressionOpt); } } else { if (memberReferenceExpressionOpt != null) { //Check against lowercase toString since it gets replaced with the lowered version before we get here if (methodName == "toString") { if (memberType.TypeKind == TypeKind.Enum || isNullableEnum) { var enumType = memberType.TypeKind == TypeKind.Enum ? memberType : memberType.As <INamedTypeSymbol>().TypeArguments.Single(); //calling ToString() on an enum forwards to our enum's special ToString method writer.Write(enumType.ContainingNamespace.FullNameWithDot()); writer.Write(WriteType.TypeName((INamedTypeSymbol)enumType)); writer.Write(".ToString("); Core.Write(writer, memberReferenceExpressionOpt.Expression); writer.Write(")"); if (invocationExpression.ArgumentList.Arguments.Count > 0) { throw new Exception( "Enum's ToString detected with parameters. These are not supported " + Utility.Descriptor(invocationExpression)); } return; } if (memberType.SpecialType == SpecialType.System_Byte) { //Calling ToString on a byte needs to take special care since it's signed in the JVM writer.Write("System.SharpNative.ByteToString("); Core.Write(writer, memberReferenceExpressionOpt.Expression); writer.Write(")"); if (invocationExpression.ArgumentList.Arguments.Count > 0) { throw new Exception( "Byte's ToString detected with parameters. These are not supported " + Utility.Descriptor(invocationExpression)); } return; } } } if (subExpressionOpt != null) { WriteMemberAccessExpression.WriteMember(writer, subExpressionOpt); // if (!(subExpressionOpt is BaseExpressionSyntax)) // { // if (methodName != null && methodSymbol.IsStatic) // writer.Write("."); // else // { if (methodSymbol.MethodKind != MethodKind.DelegateInvoke) { writer.Write("."); } // } // } // writer.Write("."); } else if (methodSymbol.IsStatic && extensionNamespace == null) { var str = TypeProcessor.ConvertType(methodSymbol.ContainingType); if (str == "Array_T") { // Array is the only special case, otherwise generics have to be specialized to access static members str = "Array"; } writer.Write(str); // writer.Write(methodSymbol.ContainingNamespace.FullNameWithDot()); // writer.Write(WriteType.TypeName(methodSymbol.ContainingType)); writer.Write("."); } if (methodSymbol.MethodKind != MethodKind.DelegateInvoke) { var declaringSyntaxReferences = methodSymbol.DeclaringSyntaxReferences.Select(j => j.GetSyntax()) .OfType <MethodDeclarationSyntax>(); var any = declaringSyntaxReferences.Any(); if (any && declaringSyntaxReferences.FirstOrDefault() .As <MethodDeclarationSyntax>() .Modifiers.Any(SyntaxKind.NewKeyword)) { //TODO: this means that new is not supported on external libraries // //why doesnt roslyn give me this information ? methodName += "_"; } if (any && declaringSyntaxReferences.FirstOrDefault() .As <MethodDeclarationSyntax>() .Modifiers.Any(SyntaxKind.NewKeyword)) { writer.Write(TypeProcessor.ConvertType(methodSymbol.ContainingType) + "."); } //TODO: fix this for abstract too or whatever other combination //TODO: create a better fix fot this // ISymbol interfaceMethod = // methodSymbol.ContainingType.AllInterfaces.SelectMany ( // u => // u.GetMembers (methodName) // .Where ( // o => // methodSymbol.ContainingType.FindImplementationForInterfaceMember (o) == // methodSymbol)).FirstOrDefault (); /* if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface || * Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol)) * * if ((interfaceMethod != null /*&& interfaceMethod == methodSymbol || methodSymbol.ContainingType.TypeKind == TypeKind.Interface) * { * //This is an interface method //TO * * var typenameM = Regex.Replace (TypeProcessor.ConvertType (methodSymbol.ContainingType), @" ?!\(.*?\)", string.Empty); * if (typenameM.Contains ('.')) * typenameM = typenameM.SubstringAfterLast ('.'); * if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array) * writer.Write (""); * else if (interfaceMethod != null) * { * var typenameI = Regex.Replace (TypeProcessor.ConvertType (interfaceMethod.ContainingType), @" ?!\(.*?\)", string.Empty); * if (typenameI.Contains ('.')) * typenameI = typenameI.SubstringAfterLast ('.'); * writer.Write (typenameI + "_"); * } * else // this is the interface itself * writer.Write (typenameM + "_"); * * }*/ if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface || Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol)) { methodName = Regex.Replace( TypeProcessor.ConvertType(methodSymbol.ContainingType.OriginalDefinition) .RemoveFromStartOfString(methodSymbol.ContainingNamespace + ".Namespace.") + "_" + methodName, @" ?!\(.*?\)", string.Empty); } var interfaceMethods = methodSymbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(methodName)).ToArray(); ISymbol interfaceMethod = interfaceMethods.FirstOrDefault( o => methodSymbol.ContainingType.FindImplementationForInterfaceMember(o) == methodSymbol); // if (interfaceMethod == null) // { // //TODO: fix this for virtual method test 7, seems roslyn cannot deal with virtual // // overrides of interface methods ... so i'll provide a kludge // if (!method.Modifiers.Any(SyntaxKind.NewKeyword)) // interfaceMethod = interfaceMethods.FirstOrDefault(k => CompareMethods(k as IMethodSymbol, methodSymbol)); // } if (interfaceMethod != null) // && CompareMethods(interfaceMethod ,methodSymbol)) { { //This is an interface method //TO if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array) { writer.Write(""); } else { var typenameI = Regex.Replace( TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom, true), @" ?!\(.*?\)", string.Empty); //TODO: we should be able to get the original interface name, or just remove all generics from this if (typenameI.Contains('.')) { typenameI = typenameI.SubstringAfterLast('.'); } writer.Write(typenameI + "_"); } } // var acc = methodSymbol.DeclaredAccessibility; // if (methodSymbol.MethodKind == MethodKind.ExplicitInterfaceImplementation) // { // var implementations = methodSymbol.ExplicitInterfaceImplementations[0]; // if (implementations != null) // { // // explicitHeaderNAme = implementations.Name; // methodName = TypeProcessor.ConvertType(implementations.ReceiverType) + "_" +implementations.Name; //Explicit fix ? // // // writer.Write(methodSymbol.ContainingType + "." + methodName); // //Looks like internal classes are not handled properly here ... // } // } writer.Write(methodName); } WriteTypeParameters(writer, typeParameters, invocationExpression); writer.Write("("); } bool inParams = false; bool foundParamsArray = false; var arguments = invocationExpression.ArgumentList.Arguments; foreach (var arg in arguments.Select(o => new TransformedArgument(o))) { if (firstParameter) { firstParameter = false; } else { writer.Write(", "); } var argumentType = TypeProcessor.GetTypeInfo(arg.ArgumentOpt.Expression); // if (!inParams && IsParamsArgument (invocationExpression, arg.ArgumentOpt, methodSymbol)) // { // foundParamsArray = true; // // if (!TypeProcessor.ConvertType (TypeProcessor.GetTypeInfo (arg.ArgumentOpt.Expression).Type).StartsWith ("System.Array<")) // { // inParams = true; // writer.Write ("Array_T!("); // } // } //Not needed for dlang // if (arg != null // && arg.ArgumentOpt.RefOrOutKeyword.RawKind != (decimal) SyntaxKind.None // && TypeProcessor.GetSymbolInfo(arg.ArgumentOpt.Expression).Symbol is IFieldSymbol) // { // // } // throw new Exception("ref/out cannot reference fields, only local variables. Consider using ref/out on a local variable and then assigning it into the field. " + Utility.Descriptor(invocationExpression)); // if (argumentType.Type == null) { // if (argumentType.ConvertedType == null) // writer.Write ("null"); // else // writer.Write ("(cast("+TypeProcessor.ConvertType(argumentType.ConvertedType)+") null)"); // } // // else if (argumentType.Type.IsValueType && !argumentType.ConvertedType.IsValueType) // { // //Box // writer.Write("BOX!("+TypeProcessor.ConvertType(argumentType.Type) +")("); // //When passing an argument by ref or out, leave off the .Value suffix // if (arg != null && arg.ArgumentOpt.RefOrOutKeyword.RawKind != (decimal)SyntaxKind.None) // WriteIdentifierName.Go(writer, arg.ArgumentOpt.Expression.As<IdentifierNameSyntax>(), true); // else // arg.Write(writer); // // writer.Write(")"); // } // else if (!argumentType.Type.IsValueType && argumentType.ConvertedType.IsValueType) // { // //UnBox // writer.Write("cast(" + TypeProcessor.ConvertType(argumentType.Type) + ")("); // if (arg != null && arg.ArgumentOpt.RefOrOutKeyword.RawKind != (decimal)SyntaxKind.None) // WriteIdentifierName.Go(writer, arg.ArgumentOpt.Expression.As<IdentifierNameSyntax>(), true); // else // arg.Write(writer); // writer.Write(")"); // } // else // { // if (arg != null && arg.ArgumentOpt.RefOrOutKeyword.RawKind != (decimal)SyntaxKind.None) // WriteIdentifierName.Go(writer, arg.ArgumentOpt.Expression.As<IdentifierNameSyntax>(), true); // else // arg.Write(writer); // } ProcessArgument(writer, arg.ArgumentOpt); } // if (inParams) // writer.Write (")"); // if (!foundParamsArray && methodSymbol.Parameters.Any () && methodSymbol.Parameters.Last ().IsParams) // writer.Write (", null"); //params method called without any params argument. Send null. writer.Write(")"); }
public static void Go(OutputWriter writer, MemberAccessExpressionSyntax expression) { var memberName = expression.Name.Identifier.ValueText; var type = TypeProcessor.GetTypeInfo(expression.Expression).ConvertedType; var typeStr = TypeProcessor.GenericTypeName(type); var isLiteral = expression.Expression is LiteralExpressionSyntax; var isStringLiteral = false; if (isLiteral) { var literal = expression.Expression as LiteralExpressionSyntax; if (literal.RawKind == (decimal)SyntaxKind.StringLiteralExpression) { isStringLiteral = true; // writer.Write("((System.String)"); Not needed for strings at all } } memberName = WriteIdentifierName.TransformIdentifier(memberName); var typeInfo = TypeProcessor.GetTypeInfo(expression.Expression); var symbolInfo = TypeProcessor.GetSymbolInfo(expression); if (symbolInfo.Symbol == null) { symbolInfo = TypeProcessor.GetSymbolInfo(expression.Expression); } if (type != null && symbolInfo.Symbol != null) //if type is null, then we're just a namespace. We can ignore these. { var directInvocationOnBasics = symbolInfo.Symbol.ContainingType.IsBasicType(); if (directInvocationOnBasics) { // var extensionNamespace = symbolInfo.Symbol.ContainingNamespace.FullNameWithDot() + symbolInfo.Symbol.ContainingType.FullName(); //null means it's not an extension method, non-null means it is //Extension methods in Dlang are straightforward, although this could lead to clashes without qualification var extensionNamespace = type.ContainingNamespace.FullName() + "." + type.Name; //memberType.ContainingNamespace.FullName() +"."+ memberType.Name; writer.Write(extensionNamespace); } else { WriteMember(writer, expression.Expression); } if (isLiteral && !isStringLiteral) { writer.Write(")"); //Not needed for strings at all } writer.Write("."); // Ideally Escape analysis should take care of this, but for now all value types are on heap and ref types on stack } if (symbolInfo.Symbol != null && symbolInfo.Symbol.Kind == SymbolKind.Property) { if (symbolInfo.Symbol.ContainingType.TypeKind == TypeKind.Interface || Equals(symbolInfo.Symbol.ContainingType.FindImplementationForInterfaceMember(symbolInfo.Symbol), symbolInfo.Symbol)) { memberName = Regex.Replace( TypeProcessor.ConvertType(symbolInfo.Symbol.ContainingType.OriginalDefinition) .RemoveFromStartOfString(symbolInfo.Symbol.ContainingNamespace + ".Namespace.") + "_" + memberName, @" ?!\(.*?\)", string.Empty); } var interfaceMethods = symbolInfo.Symbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(memberName)).ToArray(); ISymbol interfaceMethod = interfaceMethods.FirstOrDefault( o => symbolInfo.Symbol.ContainingType.FindImplementationForInterfaceMember(o) == symbolInfo.Symbol); if (interfaceMethod != null) { //This is an interface method //TO if (symbolInfo.Symbol.ContainingType.SpecialType == SpecialType.System_Array) { writer.Write(""); } else { var typenameI = Regex.Replace( TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom, true), @" ?!\(.*?\)", string.Empty); //TODO: we should be able to get the original interface name, or just remove all generics from this if (typenameI.Contains('.')) { typenameI = typenameI.SubstringAfterLast('.'); } writer.Write(typenameI + "_"); } } if (!symbolInfo.Symbol.ContainingType.IsAnonymousType && (symbolInfo.Symbol.DeclaringSyntaxReferences.Any() && symbolInfo.Symbol.DeclaringSyntaxReferences.FirstOrDefault() .GetSyntax() .As <PropertyDeclarationSyntax>() .Modifiers.Any(SyntaxKind.NewKeyword))) { //TODO: this means that new is not supported on external libraries, anonymous types cannot be extended // //why doesnt roslyn give me this information ? memberName += "_"; } } var isGet = false; writer.Write(memberName); if (expression.Name is GenericNameSyntax) { var gen = expression.Name.As <GenericNameSyntax>(); writer.Write("!( "); bool first = true; foreach (var g in gen.TypeArgumentList.Arguments) { if (first) { first = false; } else { writer.Write(", "); } writer.Write(TypeProcessor.ConvertType(g)); } writer.Write(" )"); } }
public static void Go(OutputWriter writer, MemberAccessExpressionSyntax expression) { var memberName = expression.Name.Identifier.Text; var type = TypeProcessor.GetTypeInfo(expression.Expression).ConvertedType; var typeStr = TypeProcessor.GenericTypeName(type); var isLiteral = expression.Expression is LiteralExpressionSyntax; var isStringLiteral = false; if (isLiteral) { var literal = expression.Expression as LiteralExpressionSyntax; if (literal.RawKind == (decimal)SyntaxKind.StringLiteralExpression) { isStringLiteral = true; // writer.Write("((System.String)"); Not needed for strings at all } } memberName = WriteIdentifierName.TransformIdentifier(memberName); var typeInfo = TypeProcessor.GetTypeInfo(expression.Expression); var symbolInfo = TypeProcessor.GetSymbolInfo(expression); var methodSymbol = symbolInfo.Symbol; if (methodSymbol == null) { symbolInfo = TypeProcessor.GetSymbolInfo(expression.Expression); } if (type != null && methodSymbol != null) //if type is null, then we're just a namespace. We can ignore these. { var directInvocationOnBasics = methodSymbol.ContainingType.IsBasicType() && methodSymbol.IsStatic; if (directInvocationOnBasics) { //Extension methods in Dlang are straightforward, although this could lead to clashes without qualification if (methodSymbol.ContainingType != Context.Instance.Type) { var extensionNamespace = TypeProcessor.ConvertType(type, true, false); writer.Write(extensionNamespace); } } else { WriteMember(writer, expression.Expression); } if (isLiteral && !isStringLiteral) { writer.Write(")"); //Not needed for strings at all } writer.Write("."); // Ideally Escape analysis should take care of this, but for now all value types are on heap and ref types on stack } if (methodSymbol != null && methodSymbol.Kind == SymbolKind.Property) { if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface || Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol)) { /* memberName = * Regex.Replace( * TypeProcessor.ConvertType(methodSymbol.ContainingType.OriginalDefinition) * .RemoveFromStartOfString(methodSymbol.ContainingNamespace + ".Namespace.") + * "_" + memberName, * @" ?!\(.*?\)", string.Empty);*/ if (methodSymbol.ContainingType.ContainingType != null) { memberName = memberName.RemoveFromStartOfString(methodSymbol.ContainingType.ContainingType.Name + "."); } } string name = memberName; var interfaceMethods = methodSymbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(name)).ToArray(); ISymbol interfaceMethod = interfaceMethods.FirstOrDefault( o => Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(o), methodSymbol)); if (interfaceMethod != null) { //This is an interface method //TO if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array) { writer.Write(""); } else { /* var typenameI = * Regex.Replace( * TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom, true), * @" ?!\(.*?\)", string.Empty); * //TODO: we should be able to get the original interface name, or just remove all generics from this * if (typenameI.Contains('.')) * typenameI = typenameI.SubstringAfterLast('.'); * writer.Write(typenameI + "_");*/ } } /* if (!methodSymbol.ContainingType.IsAnonymousType && * (methodSymbol.DeclaringSyntaxReferences.Any() && * methodSymbol.DeclaringSyntaxReferences.FirstOrDefault() * .GetSyntax() * .As<PropertyDeclarationSyntax>() * .Modifiers.Any(SyntaxKind.NewKeyword))) * { * //TODO: this means that new is not supported on external libraries, anonymous types cannot be extended * // //why doesnt roslyn give me this information ? * memberName += "_"; * }*/ } var isGet = false; writer.Write(memberName); // if (methodSymbol is IMethodSymbol) //Lets specialize it // { // // //Type inference for delegates // var mmethodSymbol = methodSymbol as IMethodSymbol; // // var specialization = // (mmethodSymbol.TypeArguments.Any() ? ("!(" + // mmethodSymbol.TypeArguments.Select(k => TypeProcessor.ConvertType(k)) // .Aggregate((a, b) => a + "," + b) + ")") : ""); // writer.Write(specialization); // } /* if (expression.Name is GenericNameSyntax) * { * var gen = expression.Name.As<GenericNameSyntax>(); * * writer.Write("!("); * * bool first = true; * foreach (var g in gen.TypeArgumentList.Arguments) * { * if (first) * first = false; * else * writer.Write(", "); * * writer.Write(TypeProcessor.ConvertType(g)); * } * * writer.Write(")"); * }*/ }
public void Write(OutputWriter writer) { if (StringOpt != null) { writer.Write(StringOpt); } else { if (ArgumentOpt.NameColon != null) { Core.Write(writer, ArgumentOpt.NameColon.Name); writer.Write(" = "); } var symbol = TypeProcessor.GetSymbolInfo(ArgumentOpt.Expression); var type = TypeProcessor.GetTypeInfo(ArgumentOpt.Expression); if (symbol.Symbol != null && type.ConvertedType != null && symbol.Symbol.Kind == SymbolKind.Method && type.ConvertedType.TypeKind == TypeKind.Delegate) { var typeString = TypeProcessor.ConvertType(type.ConvertedType); var createNew = !(ArgumentOpt.Parent.Parent is ObjectCreationExpressionSyntax); //Ugly hack if (createNew) { if (type.ConvertedType.TypeKind == TypeKind.TypeParameter) { writer.Write(" __TypeNew!(" + typeString + ")("); } else { writer.Write("new " + typeString + "("); } } var isStatic = symbol.Symbol.IsStatic; if (isStatic) { writer.Write("__ToDelegate("); } writer.Write("&"); Core.Write(writer, ArgumentOpt.Expression); if (isStatic) { writer.Write(")"); } if (createNew) { writer.Write(")"); } return; } Core.Write(writer, ArgumentOpt.Expression); WriteEnum.Check(ArgumentOpt.Expression); } }
private static void ProcessExpression(OutputWriter writer, SyntaxToken operatorToken, CSharpSyntaxNode rightExpression, CSharpSyntaxNode leftExpression) { TypeInfo leftExpressionType = TypeProcessor.GetTypeInfo(leftExpression ?? rightExpression); var rightExpressionType = TypeProcessor.GetTypeInfo(rightExpression); var boxLeft = leftExpressionType.Type != null && (leftExpressionType.Type != leftExpressionType.ConvertedType) && ((leftExpressionType.Type.IsValueType || leftExpressionType.Type.TypeKind == TypeKind.TypeParameter) && (leftExpressionType.ConvertedType.IsReferenceType)); var boxRight = (rightExpressionType.ConvertedType != null && (rightExpressionType.Type != null && ((rightExpressionType.Type.IsValueType || rightExpressionType.Type.TypeKind == TypeKind.TypeParameter) && (rightExpressionType.ConvertedType.IsReferenceType)))) || (rightExpressionType.Type != null && rightExpressionType.Type.IsValueType && leftExpressionType.Type != null && leftExpressionType.Type.TypeKind == TypeKind.Error); //Fix for yield ... why does it give errortypes ? var unboxRight = rightExpressionType.ConvertedType != null && (rightExpressionType.Type != null && (rightExpressionType.Type.IsReferenceType && (rightExpressionType.ConvertedType.IsValueType))); var rightnull = rightExpression != null && rightExpression.ToFullString().Trim() == "null"; var leftnull = leftExpression != null && leftExpression.ToFullString().Trim() == "null"; var nullAssignment = (rightnull || leftnull); var val = WriteOperatorDeclaration.AllBinaryOperators.FirstOrDefault(k => k.Value == operatorToken.Text); //Matching Binary Operator Overload if (!String.IsNullOrEmpty(val.Value)) { //Try Left IEnumerable <ISymbol> members = new List <ISymbol>(); if (leftExpressionType.Type != null) { members = leftExpressionType.Type.GetMembers(val.Key); } if (rightExpressionType.Type != null) { members = members. Union(rightExpressionType.Type.GetMembers(val.Key)); } var leftExpressionString = Core.WriteString(leftExpression); if (members != null && members.Any()) { if (!(leftExpressionType.Type.IsPrimitive() && rightExpressionType.Type.IsPrimitive())) { var correctOverload = members.OfType <IMethodSymbol>() .FirstOrDefault( u => u.Parameters[0].Type == leftExpressionType.Type && u.Parameters[1].Type == rightExpressionType.Type); if (correctOverload != null) { var name = WriteIdentifierName.TransformIdentifier(OverloadResolver.MethodName(correctOverload)); writer.Write(TypeProcessor.ConvertType(correctOverload.ContainingType) + "." + name + "(" + leftExpressionString + "," + Core.WriteString(rightExpression) + ")"); return; } } } else { if (WriteOperatorDeclaration.AssignOpOperators.ContainsKey(val.Key)) { var methodName = WriteOperatorDeclaration.AllBinaryOperators.FirstOrDefault( k => k.Value == val.Value.Substring(0, 1)); // emulate c# facility to use the lower op ... //Try Left members = null; if (leftExpressionType.Type != null) { members = leftExpressionType.Type.GetMembers(methodName.Key); } if (rightExpressionType.Type != null) { members = members. Union(rightExpressionType.Type.GetMembers(methodName.Key)); } if (members != null && members.Any()) { if (!(leftExpressionType.Type.IsPrimitive() && rightExpressionType.Type.IsPrimitive())) { var correctOverload = members.OfType <IMethodSymbol>() .FirstOrDefault( u => u.Parameters[0].Type == leftExpressionType.Type && u.Parameters[1].Type == rightExpressionType.Type); if (correctOverload != null) { var name = WriteIdentifierName.TransformIdentifier( OverloadResolver.MethodName(correctOverload)); writer.Write(leftExpressionString + " = " + TypeProcessor.ConvertType(correctOverload.ContainingType) + "." + name + "(" + leftExpressionString + "," + Core.WriteString(rightExpression) + ")"); return; } } } } } } //Property calls will be fixed in a preprocessor step ... i.e. just call them if (nullAssignment) { if (rightnull) { switch (operatorToken.CSharpKind()) { case SyntaxKind.EqualsEqualsToken: writer.Write(""); break; case SyntaxKind.NotEqualsExpression: case SyntaxKind.ExclamationEqualsToken: writer.Write("!"); break; default: writer.Write(operatorToken.ToString()); break; } writer.Write("__IsNull("); Core.Write(writer, leftExpression); writer.Write(")"); return; } if (leftnull) { // writer.Write("null"); // // switch (operatorToken.CSharpKind()) // { // case SyntaxKind.EqualsEqualsToken: // writer.Write(" is "); // break; // case SyntaxKind.NotEqualsExpression: // case SyntaxKind.ExclamationEqualsToken: // writer.Write(" !is "); // break; // default: // writer.Write(operatorToken.ToString()); // break; // } // // Core.Write(writer, rightExpression); // // return; switch (operatorToken.CSharpKind()) { case SyntaxKind.EqualsEqualsToken: writer.Write(""); break; case SyntaxKind.NotEqualsExpression: case SyntaxKind.ExclamationEqualsToken: writer.Write("!"); break; default: writer.Write(operatorToken.ToString()); break; } writer.Write("__IsNull("); Core.Write(writer, rightExpression); writer.Write(")"); return; } } //Do we have an implicit converter, if so, use it if (leftExpressionType.Type != rightExpressionType.Type && rightExpressionType.Type != null) { bool useType = true; //We should start with exact converters and then move to more generic convertors i.e. base class or integers which are implicitly convertible var correctConverter = leftExpressionType.Type.GetImplicitCoversionOp(leftExpressionType.Type, rightExpressionType.Type, true); if (correctConverter == null) { useType = false; correctConverter = rightExpressionType.Type.GetImplicitCoversionOp(leftExpressionType.Type, rightExpressionType.Type, true); } if (correctConverter != null) { Core.Write(writer, leftExpression); writer.Write(operatorToken.ToString()); if (useType) { writer.Write(TypeProcessor.ConvertType(leftExpressionType.Type) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } else { writer.Write(TypeProcessor.ConvertType(rightExpressionType.Type) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } writer.Write("("); Core.Write(writer, rightExpression); writer.Write(")"); return; } } if (operatorToken.CSharpKind() == SyntaxKind.PlusEqualsToken || operatorToken.CSharpKind() == SyntaxKind.MinusEqualsToken) { var isname = rightExpression is NameSyntax; var nameexpression = rightExpression as NameSyntax; var ismemberexpression = rightExpression is MemberAccessExpressionSyntax || (isname && TypeProcessor.GetSymbolInfo(rightExpression as NameSyntax).Symbol.Kind == SymbolKind.Method); var isdelegateassignment = rightExpressionType.ConvertedType != null && (ismemberexpression && rightExpressionType.ConvertedType .TypeKind == TypeKind.Delegate); var memberaccessexpression = rightExpression as MemberAccessExpressionSyntax; var isstaticdelegate = isdelegateassignment && ((memberaccessexpression != null && TypeProcessor.GetSymbolInfo(memberaccessexpression).Symbol.IsStatic) || (isname && TypeProcessor.GetSymbolInfo(nameexpression).Symbol.IsStatic)); if (isdelegateassignment) { Core.Write(writer, leftExpression); writer.Write(operatorToken.ToString()); var typeString = TypeProcessor.ConvertType(rightExpressionType.ConvertedType); if (rightExpressionType.ConvertedType.TypeKind == TypeKind.TypeParameter) { writer.Write(" __TypeNew!(" + typeString + ")("); } else { writer.Write("new " + typeString + "("); } var isStatic = isstaticdelegate; // if (isStatic) // writer.Write("__ToDelegate("); MemberUtilities.WriteMethodPointer(writer, rightExpression); // if (isStatic) // writer.Write(")"); writer.Write(")"); return; } } if (leftExpressionType.Type == null || (rightExpressionType.Type == null && rightExpression != null)) { // seems we have a null here obj==null or null==obj if ((rightExpressionType.Type != null && rightExpressionType.Type.IsValueType) || (leftExpressionType.Type != null && leftExpressionType.Type.IsValueType)) { writer.Write("/*value type cannot be null*/"); Core.Write(writer, leftExpression); switch (operatorToken.CSharpKind()) { case SyntaxKind.EqualsEqualsToken: writer.Write("!="); break; case SyntaxKind.NotEqualsExpression: writer.Write("=="); break; default: writer.Write(operatorToken.ToString()); break; } Core.Write(writer, rightExpression); } else { Core.Write(writer, leftExpression); if (operatorToken.CSharpKind() == SyntaxKind.EqualsEqualsToken) { writer.Write(" is "); } else if (operatorToken.CSharpKind() == SyntaxKind.ExclamationEqualsToken) { writer.Write(" !is "); } else { writer.Write(operatorToken.ToString()); } if (rightExpression != null) { Core.Write(writer, rightExpression); } } } else { writer.Write(boxLeft ? "BOX!(" + TypeProcessor.ConvertType(leftExpressionType.Type) + ")(" : ""); Core.Write(writer, leftExpression); writer.Write(boxLeft ? ")" : ""); writer.Write(operatorToken.ToString()); if (rightExpression != null) { writer.Write(unboxRight ? "UNBOX!(" + TypeProcessor.ConvertType(rightExpressionType.ConvertedType) + ")(" : ""); writer.Write(boxRight ? "BOX!(" + TypeProcessor.ConvertType(rightExpressionType.Type) + ")(" : ""); Core.Write(writer, rightExpression); writer.Write(boxRight ? ")" : ""); writer.Write(unboxRight ? ")" : ""); } } }
public static void Go(OutputWriter writer, IdentifierNameSyntax identifier, bool byRef = false) { var symbol = TypeProcessor.GetSymbolInfo(identifier).Symbol; if (symbol.IsStatic) { writer.Write(symbol.ContainingNamespace.FullNameWithDot()); writer.Write(symbol.ContainingType.FullName()); writer.Write("."); } // if (!byRef && Program.RefOutSymbols.ContainsKey(symbol)) //Not neccessary, c++ can pass by ref // { // writer.Write("(*"); // writer.Write(TransformIdentifier(identifier.Identifier.ToString())); // writer.Write(")"); // } // else // { var binExpression = identifier.Parent as BinaryExpressionSyntax; string memberName = TransformIdentifier(identifier.Identifier.ToString()); if (symbol.Kind == SymbolKind.Property) // Using dlang properties { if (symbol.ContainingType.TypeKind == TypeKind.Interface || Equals(symbol.ContainingType.FindImplementationForInterfaceMember(symbol), symbol)) { memberName = Regex.Replace( TypeProcessor.ConvertType(symbol.ContainingType.OriginalDefinition) .RemoveFromStartOfString(symbol.ContainingNamespace + ".Namespace.") + "_" + memberName, @" ?!\(.*?\)", string.Empty); } var interfaceMethods = symbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(memberName)).ToArray(); ISymbol interfaceMethod = interfaceMethods.FirstOrDefault( o => symbol.ContainingType.FindImplementationForInterfaceMember(o) == symbol); // if (interfaceMethod == null) // { // //TODO: fix this for virtual method test 7, seems roslyn cannot deal with virtual // // overrides of interface methods ... so i'll provide a kludge // if (!method.Modifiers.Any(SyntaxKind.NewKeyword)) // interfaceMethod = interfaceMethods.FirstOrDefault(k => CompareMethods(k as IMethodSymbol, methodSymbol)); // } if (interfaceMethod != null) // && CompareMethods(interfaceMethod ,methodSymbol)) { { //This is an interface method //TO if (symbol.ContainingType.SpecialType == SpecialType.System_Array) { writer.Write(""); } else { var typenameI = Regex.Replace( TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom, true), @" ?!\(.*?\)", string.Empty); //TODO: we should be able to get the original interface name, or just remove all generics from this if (typenameI.Contains('.')) { typenameI = typenameI.SubstringAfterLast('.'); } writer.Write(typenameI + "_"); } } // var closeBraces = binExpression != null && binExpression.IsKind(SyntaxKind.SimpleAssignmentExpression) && binExpression.Left == identifier?"()" :""; // if (binExpression != null && binExpression.OperatorToken.RawKind == (decimal) SyntaxKind.EqualsToken) // { // // writer.Write("set_" + memberName + closeBraces); // // } // else // { // writer.Write("get_" + memberName+ closeBraces); // // } } // else { writer.Write(memberName); } // } }
private static void ProcessInitializer(OutputWriter writer, LocalDeclarationStatementSyntax declaration, VariableDeclaratorSyntax variable) { var initializer = variable.Initializer; if (initializer != null) { if (initializer.Value.CSharpKind() == SyntaxKind.CollectionInitializerExpression) { return; } var value = initializer.Value; var initializerType = TypeProcessor.GetTypeInfo(value); var memberaccessexpression = value as MemberAccessExpressionSyntax; var nameexpression = value as NameSyntax; var nullAssignment = value.ToFullString().Trim() == "null"; var convertedType = initializerType.ConvertedType; var type = initializerType.Type; if (type == null && convertedType == null) //TODO: Rare Case (Compiling csnative corlib... need to find a solution, for now just write it out { Core.Write(writer, value); return; } var shouldBox = type != null && (type.IsValueType) && !convertedType.IsValueType; var shouldUnBox = type != null && !type.IsValueType && convertedType.IsValueType; var isname = value is NameSyntax; var ismemberexpression = value is MemberAccessExpressionSyntax || (isname && TypeProcessor.GetSymbolInfo(value as NameSyntax).Symbol.Kind == SymbolKind.Method); var isdelegateassignment = ismemberexpression && convertedType.TypeKind == TypeKind.Delegate; var isstaticdelegate = isdelegateassignment && ((memberaccessexpression != null && TypeProcessor.GetSymbolInfo(memberaccessexpression).Symbol.IsStatic) || (isname && TypeProcessor.GetSymbolInfo(nameexpression).Symbol.IsStatic)); //Do we have an implicit converter, if so, use it if (shouldBox || shouldUnBox) { if (WriteConverter(writer, type, convertedType, value)) { return; } } if (nullAssignment) { if (convertedType != null) //Nullable Support { if (convertedType.Name == "Nullable") { var atype = TypeProcessor.ConvertType(convertedType); writer.Write(atype + "()"); } else { writer.Write("null"); } } return; } if (shouldBox) { WriteBox(writer, type, value); return; } if (shouldUnBox) { WriteUnbox(writer, type, value); return; } if (isdelegateassignment) { WriteDelegateAssignment(writer, convertedType, isstaticdelegate, value); return; } // if (type == null && convertedType == null) // { // writer.Write("null"); // return; // } //CTFE /* var aVal = EvaluateValue(value); * if (String.IsNullOrEmpty(aVal)) * { * writer.Write(aVal); * } * else*/ Core.Write(writer, value); } else { writer.Write(TypeProcessor.DefaultValue(declaration.Declaration.Type)); } }
private static void WriteOutOneType(OutputWriter parentModuleWriter, Context.SyntaxAndSymbol[] typeSymbols, bool fileExists) { TypeProcessor.ClearUsedTypes(); var mynamespace = Context.Instance.Type.ContainingNamespace.FullName().RemoveFromEndOfString(".Namespace"); var fullname = Context.Instance.Namespace + "." + Context.Instance.TypeName; if (TypeRenames.ContainsKey(fullname)) { Context.Instance.TypeName = TypeRenames[fullname]; } // + "." + TypeState.Instance.TypeName; // if (Driver.Verbose) // Console.WriteLine("Writing out type: " + fullname); if (fullname.StartsWith( "System.Collections.Generic.Dictionary")) { } var myUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(mynamespace)); var SystemUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")); // Required as certain functions like boxing are in this namespace var namespaces = typeSymbols.First().Syntax.Parent.DescendantNodes().OfType <UsingDirectiveSyntax>().ToArray(); var usingStatements = typeSymbols.First().Syntax.Parent.DescendantNodes().OfType <UsingStatementSyntax>().ToArray(); var allTypeAliases = typeSymbols.First().Syntax.DescendantNodes().OfType <QualifiedNameSyntax>().ToArray(); Context.Instance.UsingDeclarations = namespaces .Union(new[] { myUsingDirective, SystemUsingDirective }).ToArray(); TypeProcessor.AddAlias(Context.Instance.Type.ContainingNamespace as INamespaceSymbol, Context.Instance.Type.ContainingNamespace.GetModuleName()); foreach (var ns in namespaces) { //TODO: Add support for type aliases ... var symbol = TypeProcessor.GetSymbolInfo(ns.Name).Symbol; if (allTypeAliases.All(o => TypeProcessor.GetSymbolInfo(o.Left).Symbol != symbol)) { TypeProcessor.AddAlias(symbol as INamespaceSymbol, (symbol as INamespaceSymbol).GetModuleName()); } } var aliases = allTypeAliases.DistinctBy(j => TypeProcessor.GetSymbolInfo(j.Left)); foreach (var alias in aliases) { var left = alias.Left; var type = TypeProcessor.GetSymbolInfo(left).Symbol as INamespaceSymbol; var name = left.ToString(); if (type != null && type.ToString() != name) { TypeProcessor.AddAlias(type, name); } } OutputWriter writer = null; using ( writer = parentModuleWriter == null ? new OutputWriter(Context.Instance.Namespace, Context.Instance.TypeName) : new TempWriter()) { writer.FileExists = fileExists; if (parentModuleWriter != null) { writer.WriteLine(); writer.Indent = parentModuleWriter.Indent + 2; writer.WriteIndent(); } var bases = new List <ITypeSymbol>(); var baselist = typeSymbols.Select(k => k.Syntax.As <BaseTypeDeclarationSyntax>()).Select(o => o.BaseList).Where(k => k != null).ToArray(); if (baselist.Any()) { bases = baselist.SelectMany(k => k.Types) .Select(o => TypeProcessor.GetTypeInfo(o.Type).ConvertedType ?? TypeProcessor.GetTypeInfo(o.Type).Type) .Where(k => k != null) .Distinct() .ToList(); } // var interfaces = bases.Where(o => o.TypeKind == TypeKind.Interface).ToList(); if (Context.Instance.Type != Context.Object) { if (bases != null && (!bases.Any((j => j.TypeKind != TypeKind.Interface)) && !(typeSymbols.First().Symbol.TypeKind == TypeKind.Interface || typeSymbols.First().Symbol.TypeKind == TypeKind.Struct))) { //TODO: fix structs using mixins / alias this bases.Add(Context.Object); } } if (bases == null) { bases = new List <ITypeSymbol>(); } foreach (var type in bases) { TypeProcessor.AddUsedType(type); } //TODO: Fix enum support if (typeSymbols.First().Syntax is EnumDeclarationSyntax) { WriteEnum.Go(writer, Context.Instance.Partials.Select(o => o.Syntax) .Cast <EnumDeclarationSyntax>() .SelectMany(o => o.Members) .Where(o => !Program.DoNotWrite.ContainsKey(o))); if (parentModuleWriter != null) { parentModuleWriter.Write(writer.ToString()); } return; } Context.Instance.AllMembers = typeSymbols.Select(k => k.Syntax.As <TypeDeclarationSyntax>()).SelectMany(o => o.Members) .Where(o => !Program.DoNotWrite.ContainsKey(o)) .ToList(); var allMembersToWrite = Context.Instance.AllMembers .Where(member => !(member is TypeDeclarationSyntax) && !(member is EnumDeclarationSyntax) && !(member is DelegateDeclarationSyntax) && !(member is ConstructorDeclarationSyntax)) .ToList(); Context.Instance.MemberNames = allMembersToWrite.Select(k => k.GetCSharpName()).ToList(); if (Context.Instance.Type.ContainingType != null) { Context.Instance.MemberNames.AddRange(Context.Instance.Type.ContainingType.MemberNames); } { // WriteStandardIncludes.Go(writer); // writer.WriteLine(String.Format("#include \"{0}\"", TypeState.Instance.TypeName + ".h")); WriteBcl.Go(writer); //TypeState.Instance.DerivesFromObject = bases.Count == interfaces.Count; var @namespace = typeSymbols.First().Symbol.ContainingNamespace.FullName(); var genericArgs = Context.Instance.Type.TypeParameters.Select(l => l as ITypeSymbol).ToList(); //Module name = namespace + "." + typename; WriteStandardIncludes.Go(writer); // var namespaces = @namespace.Split(new string[] { "." }, StringSplitOptions.None); // // if (@namespace.Length > 0) // { // foreach (var ns in namespaces) // { // writer.WriteLine("namespace " + ns + "\r\n{"); // writer.WriteLine("namespace " + ns + "\r\n{"); // } // // } var instanceCtors = Context.Instance.AllMembers.OfType <ConstructorDeclarationSyntax>() .Where(o => !o.Modifiers.Any(SyntaxKind.StaticKeyword)) .ToList(); var staticCtors = Context.Instance.AllMembers.OfType <ConstructorDeclarationSyntax>() .Where(o => (o.Modifiers.Any(SyntaxKind.StaticKeyword))) .ToList(); //TODO: Add support for overloading constructing // if (instanceCtors.Count > 1) // throw new Exception( // "Overloaded constructors are not supported. Consider changing all but one to static Create methods " + // Utility.Descriptor(first.Syntax)); // var ctorOpt = instanceCtors.SingleOrDefault(); //TODO: Handle interfaces by /* * class Interface * { * public: * virtual ~Interface() { } * virtual void test() = 0; // Functions, must all be virtual * } */ var membersToWrite = allMembersToWrite.ToList(); //.Where(o => IsStatic(o) == staticMembers).ToList(); // if (membersToWrite.Count == 0 && (partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.StaticKeyword)))) // continue; // if (staticMembers) // writer.Write("object "); // else if (first.Syntax.Kind == SyntaxKind.InterfaceDeclaration) // writer.Write("trait "); // else // { // if (partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.AbstractKeyword))) // writer.Write("abstract "); // } // writer.Write(TypeState.Instance.TypeName); if (typeSymbols.First().Syntax is TypeDeclarationSyntax) { //Internal classes/structs are declared static in D to behave correctly if (parentModuleWriter != null) { writer.Write("static "); } if (Context.Instance.Type.TypeKind == TypeKind.Class) { writer.Write("class "); } else if (Context.Instance.Type.TypeKind == TypeKind.Interface) { writer.Write("interface "); } else if (Context.Instance.Type.TypeKind == TypeKind.Struct) { writer.Write("struct "); // writer.Write (" class "); // Allows inheritance ... but too many issues, will look at this when it gets relevant } else { throw new Exception("don't know how to write type: " + Context.Instance.Type.TypeKind); } List <ITypeSymbol> parentTypeParameters; if (Context.Instance.Type.ContainingType != null) { parentTypeParameters = GetParentTypeParameters(Context.Instance.Type); } else { parentTypeParameters = new List <ITypeSymbol>(); } writer.Write(TypeName(Context.Instance.Type, false)); //TypeProcessor.ConvertType(Context.Instance.Type, true, false,true)); if (Context.Instance.Type.IsGenericType) { { foreach (var @base in bases) { var namedTypeSymbol = @base as INamedTypeSymbol; if (namedTypeSymbol != null) { foreach (var arg in namedTypeSymbol.TypeArguments) { if (arg.TypeKind == TypeKind.TypeParameter && !parentTypeParameters.Contains(arg)) { if (!genericArgs.Any(k => k.Name == arg.Name)) { genericArgs.Add(arg); } } } } } if (genericArgs.Any()) { writer.Write("(" + string.Join(" , ", genericArgs.Select(o => TypeProcessor.ConvertType(o, true, true, false))) + ")"); } } } bool firstBase = true; if (Context.Instance.Type.TypeKind != TypeKind.Struct) { foreach (var baseType in bases.OrderBy(o => o.TypeKind == TypeKind.Interface ? 1 : 0)) { var convertType = TypeProcessor.ConvertType(baseType); writer.Write(firstBase ? " : " : " ,"); writer.Write(convertType); firstBase = false; } } string constraints = GetTypeConstraints((TypeDeclarationSyntax)typeSymbols.First().Syntax); writer.Write(constraints); } writer.WriteLine(); writer.OpenBrace(); var nonFields = WriteFields(membersToWrite, typeSymbols.First(), writer); foreach (var member in nonFields) { // writer.WriteLine(); Core.Write(writer, member); } WriteConstructors(instanceCtors, writer); WriteStaticConstructors(staticCtors, writer); //PInvoke is now centralized, so we can call it on all libraries etc without issue writer.Indent--; WriteOutNestedTypes(typeSymbols.First(), writer); var methodSymbols = membersToWrite.OfType <MethodDeclarationSyntax>().Select(TypeProcessor.GetDeclaredSymbol); //TypeProcessor.GetDeclaredSymbol(method); if (!methodSymbols.OfType <IMethodSymbol>() .Any(k => k.Name == "ToString" && k.Parameters.Length == 0 && k.ReturnType == Context.String)) { if (Context.Instance.Type.TypeKind == TypeKind.Struct || (Context.Instance.Type.TypeKind == TypeKind.Class)) { var overrideS = Context.Instance.Type.TypeKind == TypeKind.Struct ? "" : "override "; writer.WriteLine(); writer.WriteLine("public " + overrideS + "String ToString()"); writer.OpenBrace(); writer.WriteLine("return GetType().FullName;");//Better names based on specialization writer.CloseBrace(); } } WriteOutBoxed(writer, genericArgs, bases); } if (Context.Instance.Type.TypeKind == TypeKind.Struct) { writer.WriteLine(); writer.WriteLine("public __Boxed_ __Get_Boxed()"); writer.OpenBrace(); writer.WriteLine("return new __Boxed_(this);"); writer.CloseBrace(); writer.WriteLine("alias __Get_Boxed this;"); } if (Context.Instance.Type.TypeKind != TypeKind.Interface) { writer.WriteLine(); if (Context.Instance.Type.TypeKind == TypeKind.Class) { writer.WriteLine("public override Type GetType()"); } // else if (Context.Instance.Type.TypeKind == TypeKind.Interface) // Messes with GetType overrides of objects // { // writer.WriteLine ("public final Type GetType()"); // } else if (Context.Instance.Type.TypeKind == TypeKind.Struct) { writer.WriteLine("public Type GetType()"); } writer.OpenBrace(); //if (Context.Instance.Type.TypeKind == TypeKind.Class) writer.WriteLine("return __TypeOf!(typeof(this));"); // else // writer.WriteLine("return __TypeOf!(__Boxed_);"); writer.CloseBrace(); } writer.CloseBrace(); WriteEntryMethod(writer); if (parentModuleWriter != null) { writer.Finalize(); parentModuleWriter.Write(writer.ToString()); } } }
public static void Go(OutputWriter writer, ObjectCreationExpressionSyntax expression) { var type = TypeProcessor.GetTypeInfo(expression).Type; if (expression.Initializer != null) { if (expression.Initializer.IsKind(SyntaxKind.CollectionInitializerExpression)) { var isPtr = type.IsPointer() ? "" : ""; var typeString = TypeProcessor.ConvertType(type); // + isPtr + " "; WriteNewOperator(writer, type, typeString); writer.Write("("); var intializer = expression.Initializer; intializer.WriteArrayInitializer(writer, expression.Type); writer.Write(")"); return; } writer.Write("("); Core.Write(writer, expression.Initializer); } if (type.SpecialType == SpecialType.System_Object) { //new object() results in the NObject type being made. This is only really useful for locking writer.Write("new NObject()"); } else if (type.OriginalDefinition is INamedTypeSymbol && type.OriginalDefinition.As <INamedTypeSymbol>().SpecialType == SpecialType.System_Nullable_T) { //new'ing up a Nullable<T> has special sematics in C#. If we're calling this with no parameters, just use null. Otherwise just use the parameter. if (expression.ArgumentList.Arguments.Count == 0) { writer.Write("null"); } else { Core.Write(writer, expression.ArgumentList.Arguments.Single().Expression); } } else { var methodSymbol = TypeProcessor.GetSymbolInfo(expression).Symbol.As <IMethodSymbol>(); var typeString = TypeProcessor.ConvertType(expression.Type); WriteNewOperator(writer, type, typeString); if (expression.ArgumentList != null) { bool first = true; foreach (var param in TranslateParameters(expression.ArgumentList.Arguments)) { if (first) { first = false; } else { writer.Write(", "); } param.Write(writer); } } writer.Write(")"); } }
public static void Go(OutputWriter writer, IdentifierNameSyntax identifier, bool byRef = false) { var symbolInfo = TypeProcessor.GetSymbolInfo(identifier); var symbol = symbolInfo.Symbol; if (symbol == null) { //Yield issue ... symbol = symbolInfo.CandidateSymbols[0]; } if (symbol.IsStatic) { // writer.Write(symbol.ContainingNamespace.FullNameWithDot()); // writer.Write(symbol.ContainingType.FullName()); writer.Write(TypeProcessor.ConvertType(symbol.ContainingType) + "."); } var binExpression = identifier.Parent as BinaryExpressionSyntax; string memberName = TransformIdentifier(identifier.Identifier.ToString()); if (symbol.Kind == SymbolKind.Property) // Using dlang properties { if (symbol.ContainingType.TypeKind == TypeKind.Interface || Equals(symbol.ContainingType.FindImplementationForInterfaceMember(symbol), symbol)) { memberName = Regex.Replace( TypeProcessor.ConvertType(symbol.ContainingType.OriginalDefinition) .RemoveFromStartOfString(symbol.ContainingNamespace + ".Namespace.") + "_" + memberName, @" ?!\(.*?\)", string.Empty); } var interfaceMethods = symbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(memberName)).ToArray(); ISymbol interfaceMethod = interfaceMethods.FirstOrDefault( o => symbol.ContainingType.FindImplementationForInterfaceMember(o) == symbol); if (interfaceMethod != null) { if (symbol.ContainingType.SpecialType == SpecialType.System_Array) { writer.Write(""); } else { var typenameI = Regex.Replace( TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom, true), @" ?!\(.*?\)", string.Empty); //TODO: we should be able to get the original interface name, or just remove all generics from this if (typenameI.Contains('.')) { typenameI = typenameI.SubstringAfterLast('.'); } writer.Write(typenameI + "_"); } } } writer.Write(memberName); }
public static void Go(OutputWriter writer, ElementAccessExpressionSyntax expression) { var type = TypeProcessor.GetTypeInfo(expression.Expression).Type; var typeStr = TypeProcessor.GenericTypeName(type); var additionalParam = ""; var symbol = TypeProcessor.GetSymbolInfo(expression); //This could be null if (symbol.Symbol != null) { var methodSymbol = symbol.Symbol as IPropertySymbol; //Lets find out if this is an interface implementation if (methodSymbol != null) { IEnumerable <ISymbol> interfaceMethods = methodSymbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(methodSymbol.Name)); interfaceMethods = interfaceMethods.Where( o => Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(o), methodSymbol)); if (interfaceMethods.Any()) { //Lets get the best match var interfaceMethod = interfaceMethods.FirstOrDefault(); additionalParam = "cast(" + TypeProcessor.ConvertType(interfaceMethod.ContainingType) + ")null"; } } } //type.GetMembers("this[]") //Todo if we are using unsafe / fast mode, just use array->Data()[i] should bypass bounds check and indirection also should be as fast as pure c++ arrays //though fixed syntax could fix this too ?? // writer.Write("(*"); Core.Write(writer, expression.Expression); if (type.SpecialType == SpecialType.System_Array) { // writer.Write(")"); writer.Write(".Items["); //TODO test this thoroughly } else { writer.Write("["); //TODO test this thoroughly } var first = true; foreach (var argument in expression.ArgumentList.Arguments) { if (first) { first = false; } else { writer.Write(", "); } Core.Write(writer, argument.Expression); } if (additionalParam != "") { writer.Write("," + additionalParam); } writer.Write("]"); }
private static void ProcessInitializer(OutputWriter writer, VariableDeclarationSyntax declaration, VariableDeclaratorSyntax variable) { var initializer = variable.Initializer; if (initializer != null) { if (CSharpExtensions.CSharpKind(initializer.Value) == SyntaxKind.CollectionInitializerExpression) { return; } var value = initializer.Value; var initializerType = TypeProcessor.GetTypeInfo(value); var memberaccessexpression = value as MemberAccessExpressionSyntax; var nameexpression = value as NameSyntax; var nullAssignment = value.ToFullString().Trim() == "null"; var shouldBox = initializerType.Type != null && (initializerType.Type.IsValueType) && !initializerType.ConvertedType.IsValueType; var shouldUnBox = initializerType.Type != null && !initializerType.Type.IsValueType && initializerType.ConvertedType.IsValueType; var isname = value is NameSyntax; var ismemberexpression = value is MemberAccessExpressionSyntax || (isname && TypeProcessor.GetSymbolInfo(value as NameSyntax).Symbol.Kind == SymbolKind.Method); var isdelegateassignment = ismemberexpression && initializerType.ConvertedType.TypeKind == TypeKind.Delegate; var isstaticdelegate = isdelegateassignment && ((memberaccessexpression != null && TypeProcessor.GetSymbolInfo(memberaccessexpression).Symbol.IsStatic) || (isname && TypeProcessor.GetSymbolInfo(nameexpression).Symbol.IsStatic)); var shouldCast = initializerType.Type != initializerType.ConvertedType && initializerType.ConvertedType != null; if (nullAssignment) { if (initializerType.Type != null) //Nullable Support { if (initializerType.Type.Name == "Nullable") { var atype = TypeProcessor.ConvertType(initializerType.Type); writer.Write(atype + "()"); } } else { writer.Write("null"); } return; } if (shouldBox) { //Box writer.Write("BOX!(" + TypeProcessor.ConvertType(initializerType.Type) + ")("); //When passing an argument by ref or out, leave off the .Value suffix Core.Write(writer, value); writer.Write(")"); return; } if (shouldUnBox) { writer.Write("cast(" + TypeProcessor.ConvertType(initializerType.Type) + ")("); Core.Write(writer, value); writer.Write(")"); return; } if (initializer.Parent.Parent.Parent is FixedStatementSyntax) // Fixed is a bit special { //TODO write a better fix var type = TypeProcessor.GetTypeInfo(declaration.Type); writer.Write("cast(" + TypeProcessor.ConvertType(type.Type) + ")("); Core.Write(writer, value); writer.Write(")"); return; } if (isdelegateassignment) { var typeString = TypeProcessor.ConvertType(initializerType.ConvertedType); var createNew = !(value is ObjectCreationExpressionSyntax); if (createNew) { if (initializerType.ConvertedType.TypeKind == TypeKind.TypeParameter) { writer.Write(" __TypeNew!(" + typeString + ")("); } else { writer.Write("new " + typeString + "("); } } var isStatic = isstaticdelegate; // if (isStatic) // writer.Write("__ToDelegate("); MemberUtilities.WriteMethodPointer(writer, value); // if (isStatic) // writer.Write(")"); if (createNew) { writer.Write(")"); } return; } if (initializerType.Type == null && initializerType.ConvertedType == null) { writer.Write("null"); return; } Core.Write(writer, value); } else { writer.Write(TypeProcessor.DefaultValue(declaration.Type)); } }
public static void Go(OutputWriter writer, AssignmentExpressionSyntax expression) { if (expression.OperatorToken.IsKind(SyntaxKind.AsKeyword)) { var typeinfo = TypeProcessor.GetTypeInfo(expression.Right); var isPtr = typeinfo.Type != null && typeinfo.Type.IsValueType ? "" : ""; writer.Write("cast( "); writer.Write(TypeProcessor.ConvertType(expression.Right) + isPtr); writer.Write(" )("); Core.Write(writer, expression.Left); writer.Write(")"); } else if (expression.OperatorToken.IsKind(SyntaxKind.IsKeyword)) // isCast { var leftSymbolType = TypeProcessor.GetTypeInfo(expression.Left); var rightSymbolType = TypeProcessor.GetTypeInfo(expression.Right); if (leftSymbolType.Type.IsValueType) { writer.Write("IsCast!(Boxed!("); writer.Write(TypeProcessor.ConvertType(expression.Right)); writer.Write("))"); writer.Write("("); Core.Write(writer, expression.Left); writer.Write(")"); // writer.Write("(cast(BOX!("); // writer.Write(TypeProcessor.ConvertType(expression.Right)); // writer.Write(" ) )(Boxed!( " + TypeProcessor.ConvertType(leftSymbolType.Type)); // writer.Write(" )("); // Core.Write(writer, expression.Left); // writer.Write(")) is! null)"); //Todo improve this ... though its silly to do this in the first place // writer.Write("(cast(BOX!("); // writer.Write(TypeProcessor.ConvertType(expression.Right)); // writer.Write("))(Boxed!(" + TypeProcessor.ConvertType(leftSymbolType.Type)); // writer.Write(")("); // Core.Write(writer, expression.Left); // writer.Write(")) is! null)"); } else if (rightSymbolType.Type.IsValueType) { writer.Write("IsCast!(Boxed!("); writer.Write(TypeProcessor.ConvertType(expression.Right)); writer.Write("))"); writer.Write("("); Core.Write(writer, expression.Left); writer.Write(")"); // writer.Write("(cast(Boxed!( "); // writer.Write(TypeProcessor.ConvertType(expression.Right)); // writer.Write(" ) )("); // Core.Write(writer, expression.Left); // writer.Write(") is! null)"); } else { var typeinfo = TypeProcessor.GetTypeInfo(expression.Right); var isPtr = typeinfo.Type != null && typeinfo.Type.IsValueType ? "" : ""; writer.Write("(IsCast!("); writer.Write(TypeProcessor.ConvertType(expression.Right) + isPtr); writer.Write(")("); Core.Write(writer, expression.Left); writer.Write("))"); } } else if (expression.OperatorToken.IsKind(SyntaxKind.QuestionQuestionToken)) { writer.Write("(("); Core.Write(writer, expression.Left); writer.Write(")!is null?("); Core.Write(writer, expression.Left); writer.Write("):("); Core.Write(writer, expression.Right); writer.Write("))"); } else { // if (expression.Left is ElementAccessExpressionSyntax && IsAssignmentToken((SyntaxKind) expression.OperatorToken.RawKind)) // { // var subExpr = expression.Left.As<ElementAccessExpressionSyntax>(); // var typeStr = TypeProcessor.GenericTypeName(TypeProcessor.GetTypeInfo(subExpr.Expression).Type); // // // // } Action <ExpressionSyntax> write = e => { var type = TypeProcessor.GetTypeInfo(e); //Check for enums being converted to strings by string concatenation var typeSymbol = type.Type ?? type.ConvertedType; if (expression.OperatorToken.RawKind == (decimal)SyntaxKind.PlusToken && typeSymbol.TypeKind == TypeKind.Enum) { writer.Write(typeSymbol.ContainingNamespace.FullNameWithDot()); writer.Write(WriteType.TypeName(typeSymbol.As <INamedTypeSymbol>())); writer.Write(".ToString("); Core.Write(writer, e); writer.Write(")"); } else if (expression.OperatorToken.RawKind == (decimal)SyntaxKind.PlusToken && (typeSymbol.Name == "Nullable" && typeSymbol.ContainingNamespace.FullName() == "System" && typeSymbol.As <INamedTypeSymbol>().TypeArguments.Single().TypeKind == TypeKind.Enum)) { var enumType = typeSymbol.As <INamedTypeSymbol>().TypeArguments.Single(); writer.Write(enumType.ContainingNamespace.FullNameWithDot()); writer.Write(WriteType.TypeName(enumType.As <INamedTypeSymbol>())); writer.Write(".ToString("); Core.Write(writer, e); writer.Write(")"); } else { Core.Write(writer, e); } }; var symbolInfoLeft = TypeProcessor.GetSymbolInfo(expression.Left); var symbolInfoRight = TypeProcessor.GetSymbolInfo(expression.Right); var leftExpressionType = TypeProcessor.GetTypeInfo(expression.Left); var rightExpressionType = TypeProcessor.GetTypeInfo(expression.Right); var boxLeft = leftExpressionType.Type != null && (leftExpressionType.Type.IsValueType && (leftExpressionType.ConvertedType.IsReferenceType)); var derefLeft = false; // rightExpressionType.ConvertedType != null && rightExpressionType.ConvertedType.IsReferenceType; var boxRight = rightExpressionType.ConvertedType != null && (rightExpressionType.Type != null && (rightExpressionType.Type.IsValueType && (rightExpressionType.ConvertedType.IsReferenceType))); var derefRight = rightExpressionType.ConvertedType != null && (leftExpressionType.ConvertedType != null && !leftExpressionType.ConvertedType.IsReferenceType && rightExpressionType.ConvertedType.IsReferenceType); var nullAssignment = expression.Right.ToFullString().Trim() == "null"; //Property calls will be fixed in a preprocessor step ... i.e. just call them // var propertyLeft = symbolInfoLeft.Symbol != null && symbolInfoLeft.Symbol.Kind == SymbolKind.Property; // var propertyRight = symbolInfoRight.Symbol != null && symbolInfoRight.Symbol.Kind == SymbolKind.Property; if (nullAssignment) { Core.Write(writer, expression.Left); writer.Write(" = "); writer.Write("null"); return; } //Do we have an implicit converter, if so, use it if (leftExpressionType.Type != rightExpressionType.Type) { // if (boxLeft) { bool useType = true; //We should start with exact converters and then move to more generic convertors i.e. base class or integers which are implicitly convertible var correctConverter = leftExpressionType.Type.GetImplicitCoversionOp(leftExpressionType.Type, rightExpressionType.Type); // initializerType.Type.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); if (correctConverter == null) { useType = false; correctConverter = rightExpressionType.Type.GetImplicitCoversionOp(leftExpressionType.Type, rightExpressionType.Type); //.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.Type && h.Parameters[0].Type == initializerType.ConvertedType); } if (correctConverter != null) { Core.Write(writer, expression.Left); writer.Write(" = "); if (useType) { writer.Write(TypeProcessor.ConvertType(leftExpressionType.Type) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType)); } else { writer.Write(TypeProcessor.ConvertType(rightExpressionType.Type) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType)); } writer.Write("("); Core.Write(writer, expression.Right); writer.Write(")"); return; } } // if (shouldBox) // { // bool useType = true; // var correctConverter = // initializerType.Type.GetCoversionOp(initializerType.ConvertedType, initializerType.Type);//.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.ConvertedType && h.Parameters[0].Type == initializerType.Type); // // if (correctConverter == null) // { // useType = false; // correctConverter = // initializerType.ConvertedType.GetCoversionOp(initializerType.ConvertedType, // initializerType.Type); // //.GetMembers("op_Implicit").OfType<IMethodSymbol>().FirstOrDefault(h => h.ReturnType == initializerType.ConvertedType && h.Parameters[0].Type == initializerType.Type); // } // // if (correctConverter != null) // { // if (useType) // writer.Write(TypeProcessor.ConvertType(initializerType.Type) + "." + "op_Implicit("); // else // { // writer.Write(TypeProcessor.ConvertType(initializerType.ConvertedType) + "." + "op_Implicit("); // // } // Core.Write(writer, value); // writer.Write(")"); // return; // } // } } if (expression.OperatorToken.CSharpKind() == SyntaxKind.PlusEqualsToken || expression.OperatorToken.CSharpKind() == SyntaxKind.MinusEqualsToken) { var isname = expression.Right is NameSyntax; var nameexpression = expression.Right as NameSyntax; var ismemberexpression = expression.Right is MemberAccessExpressionSyntax || (isname && TypeProcessor.GetSymbolInfo(expression.Right as NameSyntax).Symbol.Kind == SymbolKind.Method); var isdelegateassignment = ismemberexpression && rightExpressionType.ConvertedType.TypeKind == TypeKind.Delegate; var memberaccessexpression = expression.Right as MemberAccessExpressionSyntax; var isstaticdelegate = isdelegateassignment && ((memberaccessexpression != null && TypeProcessor.GetSymbolInfo(memberaccessexpression).Symbol.IsStatic) || (isname && TypeProcessor.GetSymbolInfo(nameexpression).Symbol.IsStatic)); if (isdelegateassignment) { write(expression.Left); writer.Write(expression.OperatorToken.ToString()); var createNew = !(expression.Right is ObjectCreationExpressionSyntax); var typeString = TypeProcessor.ConvertType(rightExpressionType.ConvertedType); if (createNew) { if (rightExpressionType.ConvertedType.TypeKind == TypeKind.TypeParameter) { writer.Write(" __TypeNew!(" + typeString + ")("); } else { writer.Write("new " + typeString + "("); } } var isStatic = isstaticdelegate; if (isStatic) { writer.Write("__ToDelegate("); } writer.Write("&"); write(expression.Right); //Core.Write (writer, expression.Right); if (isStatic) { writer.Write(")"); } if (createNew) { writer.Write(")"); } return; } } if (leftExpressionType.Type == null || rightExpressionType.Type == null) { // seems we have a null here obj==null or null==obj if ((rightExpressionType.Type != null && rightExpressionType.Type.IsValueType) || (leftExpressionType.Type != null && leftExpressionType.Type.IsValueType)) { writer.Write("/*value type cannot be null*/"); write(expression.Left); switch (expression.OperatorToken.CSharpKind()) { case SyntaxKind.EqualsEqualsToken: writer.Write("!="); break; case SyntaxKind.NotEqualsExpression: writer.Write("=="); break; default: writer.Write(expression.OperatorToken.ToString()); break; } write(expression.Right); } else { write(expression.Left); if (expression.OperatorToken.CSharpKind() == SyntaxKind.EqualsEqualsToken) { writer.Write(" is "); } else if (expression.OperatorToken.CSharpKind() == SyntaxKind.ExclamationEqualsToken) { writer.Write(" !is "); } else { writer.Write(expression.OperatorToken.ToString()); } write(expression.Right); } } else // if (symbolInfoLeft.Symbol != null && (symbolInfoLeft.Symbol.Kind == SymbolKind.Property && expression.OperatorToken.ValueText == "=")) //Assignment of property // { // // write(expression.Left); // writer.Write("("); // write(expression.Right); // writer.Write(")"); // } // else { // writer.Write(derefLeft ? "*(" : ""); writer.Write(boxLeft ? "BOX!(" + TypeProcessor.ConvertType(leftExpressionType.Type) + ")(" : ""); write(expression.Left); writer.Write(boxLeft ? ")" : ""); // writer.Write(derefLeft ? ")" : ""); writer.Write(expression.OperatorToken.ToString()); // writer.Write(derefRight ? "(" : ""); writer.Write(boxRight ? "BOX!(" + TypeProcessor.ConvertType(rightExpressionType.Type) + ")(" : ""); write(expression.Right); writer.Write(boxRight ? ")" : ""); // writer.Write(derefRight ? ")" : ""); } } }