public static void Go(ScalaWriter writer, ElementAccessExpressionSyntax expression) { var typeStr = TypeProcessor.GenericTypeName(Program.GetModel(expression).GetTypeInfo(expression.Expression).Type); var trans = ElementAccessTranslation.Get(typeStr); Core.Write(writer, expression.Expression); if (trans != null) { writer.Write("."); writer.Write(trans.ReplaceGet); } writer.Write("("); bool first = true; foreach (var argument in expression.ArgumentList.Arguments) { if (first) { first = false; } else { writer.Write(", "); } Core.Write(writer, argument.Expression); } writer.Write(")"); }
private static bool IsAmbiguousType(ITypeSymbol type) { switch (TypeProcessor.GenericTypeName(type)) { case "System.UInt16": case "System.UInt32": case "System.UInt64": return(true); default: return(false); } }
public static bool NeedsClassTag(INamedTypeSymbol symbol, string templateID) { //For types, unlike methods, this requires that they're specified in Translations.xml. TODO: Determine these programmatically. //var symbol = Program.GetModel(typeSyntax).GetDeclaredSymbol(typeSyntax); var trans = NeedsClassTagTranslation.Get(TypeProcessor.GenericTypeName(symbol)); if (trans == null || trans.TypesHashSet == null) { return(false); } else { return(trans.TypesHashSet.Contains(templateID)); } }
private static HashSet <string> TryGetBCLClassTags(IMethodSymbol method) { var methodStr = TypeProcessor.GenericTypeName(method.ContainingType) + "." + method.Name; var trans = NeedsClassTagTranslation.Get(methodStr); if (trans == null) { return(null); } if (trans.TypesHashSet != null) { return(trans.TypesHashSet); } else { return(method.TypeParameters.ToArray().Select(o => o.ToString()).ToHashSet(true)); } }
public static void Go(ScalaWriter writer, ForEachStatementSyntax foreachStatement) { var info = new LoopInfo(foreachStatement); var types = Program.GetModel(foreachStatement).GetTypeInfo(foreachStatement.Expression); var typeStr = TypeProcessor.GenericTypeName(types.Type); if (types.Type is IArrayTypeSymbol) { //It's faster to "while" through arrays than "for" through them writer.WriteOpenBrace(); info.WritePreLoop(writer); writer.WriteLine("var __foreachindex:Int = 0;"); writer.WriteIndent(); writer.Write("val __foreacharray = "); Core.Write(writer, foreachStatement.Expression); writer.Write(";\r\n"); writer.WriteLine("while (__foreachindex < __foreacharray.length)"); writer.WriteOpenBrace(); writer.WriteIndent(); writer.Write("val "); writer.Write(WriteIdentifierName.TransformIdentifier(foreachStatement.Identifier.ValueText)); writer.Write(" = __foreacharray(__foreachindex);\r\n"); info.WriteLoopOpening(writer); Core.WriteStatementAsBlock(writer, foreachStatement.Statement, false); info.WriteLoopClosing(writer); writer.WriteLine("__foreachindex += 1;"); writer.WriteCloseBrace(); info.WritePostLoop(writer); writer.WriteCloseBrace(); } else if (typeStr == "System.Collections.Generic.List<>" //|| typeStr == "System.Collections.Generic.Dictionary<,>" || typeStr == "System.Collections.Generic.Dictionary<,>.KeyCollection" || typeStr == "System.Collections.Generic.Dictionary<,>.ValueCollection") { //It's faster to "while" over a list's iterator than to "for" through it writer.WriteOpenBrace(); info.WritePreLoop(writer); writer.WriteIndent(); writer.Write("val __foreachiterator = "); Core.Write(writer, foreachStatement.Expression); writer.Write(".iterator();\r\n"); writer.WriteLine("while (__foreachiterator.hasNext())"); writer.WriteOpenBrace(); writer.WriteIndent(); writer.Write("val "); writer.Write(WriteIdentifierName.TransformIdentifier(foreachStatement.Identifier.ValueText)); writer.Write(" = __foreachiterator.next();\r\n"); info.WriteLoopOpening(writer); Core.WriteStatementAsBlock(writer, foreachStatement.Statement, false); info.WriteLoopClosing(writer); writer.WriteCloseBrace(); info.WritePostLoop(writer); writer.WriteCloseBrace(); } else { info.WritePreLoop(writer); writer.WriteIndent(); writer.Write("for ("); writer.Write(WriteIdentifierName.TransformIdentifier(foreachStatement.Identifier.ValueText)); writer.Write(" <- "); Core.Write(writer, foreachStatement.Expression); writer.Write(")\r\n"); writer.WriteOpenBrace(); info.WriteLoopOpening(writer); Core.WriteStatementAsBlock(writer, foreachStatement.Statement, false); info.WriteLoopClosing(writer); writer.WriteCloseBrace(); info.WritePostLoop(writer); } }
private static void Go(ScalaWriter writer, ExpressionSyntax left, SyntaxToken operatorToken, ExpressionSyntax right) { if (operatorToken.Kind() == SyntaxKind.AsKeyword) { writer.Write("CsScala.As["); writer.Write(TypeProcessor.ConvertType(right)); writer.Write("]("); Core.Write(writer, left); writer.Write(")"); } else if (operatorToken.Kind() == SyntaxKind.IsKeyword) { Core.Write(writer, left); writer.Write(".isInstanceOf["); writer.Write(TypeProcessor.ConvertType(right)); writer.Write("]"); } else if (operatorToken.Kind() == SyntaxKind.QuestionQuestionToken) { writer.Write("CsScala.Coalesce("); Core.Write(writer, left); writer.Write(", "); Core.Write(writer, right); writer.Write(")"); } else { if (left is ElementAccessExpressionSyntax && IsAssignmentToken(operatorToken.Kind())) { var subExpr = left.As <ElementAccessExpressionSyntax>(); var typeStr = TypeProcessor.GenericTypeName(Program.GetModel(left).GetTypeInfo(subExpr.Expression).Type); var trans = ElementAccessTranslation.Get(typeStr); if (trans != null) { Core.Write(writer, subExpr.Expression); writer.Write("."); if (operatorToken.Kind() == SyntaxKind.EqualsToken) { writer.Write(trans.ReplaceAssign); } else { throw new Exception(operatorToken.Kind() + " is not supported on " + typeStr + " " + Utility.Descriptor(left.Parent)); } writer.Write("("); foreach (var arg in subExpr.ArgumentList.Arguments) { Core.Write(writer, arg.Expression); writer.Write(", "); } Core.Write(writer, right); writer.Write(")"); return; } } Action <ExpressionSyntax> write = e => { var model = Program.GetModel(left); var type = model.GetTypeInfo(e); //Check for enums being converted to strings by string concatenation if (operatorToken.Kind() == SyntaxKind.PlusToken && type.Type.TypeKind == TypeKind.Enum) { writer.Write(type.Type.ContainingNamespace.FullNameWithDot()); writer.Write(WriteType.TypeName(type.Type.As <INamedTypeSymbol>())); writer.Write(".ToString("); Core.Write(writer, e); writer.Write(")"); } else if (operatorToken.Kind() == SyntaxKind.PlusToken && (type.Type.Name == "Nullable" && type.Type.ContainingNamespace.FullName() == "System" && type.Type.As <INamedTypeSymbol>().TypeArguments.Single().TypeKind == TypeKind.Enum)) { var enumType = type.Type.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 if (operatorToken.Kind() == SyntaxKind.PlusToken && IsException(type.Type)) //Check for exceptions being converted to strings by string concatenation { writer.Write("System.CsScala.ExceptionToString("); Core.Write(writer, e); writer.Write(")"); } else if (operatorToken.Kind() == SyntaxKind.PlusToken && type.Type.SpecialType == SpecialType.System_Byte && !Utility.IsNumeric(type.ConvertedType)) { //bytes are signed in the JVM, so we need to take care when converting them to strings. Exclude numeric types, since Core.Writer will convert these to ints writer.Write("System.CsScala.ByteToString("); Core.Write(writer, e); writer.Write(")"); } else if (operatorToken.Kind() == SyntaxKind.PlusToken && !(e is BinaryExpressionSyntax) && type.Type.SpecialType == SpecialType.System_String && CouldBeNullString(model, e)) { //In .net, concatenating a null string does not alter the output. However, in the JVM, it produces the "null" string. To counter this, we must check non-const strings. writer.Write("System.CsScala.NullCheck("); Core.Write(writer, e); writer.Write(")"); } else if (operatorToken.Kind() == SyntaxKind.PlusToken && !(e is BinaryExpressionSyntax) && type.Type is INamedTypeSymbol && type.Type.As <INamedTypeSymbol>().ConstructedFrom.SpecialType == SpecialType.System_Nullable_T) { //Concatening a nullable type in .net just produces an empty string if it's null. In scala it produces "null" or a null reference exception -- we want neither. writer.Write("System.CsScala.NullCheck("); Core.Write(writer, e); writer.Write(")"); } else if (operatorToken.Kind() == SyntaxKind.PlusToken && !(e is BinaryExpressionSyntax) && type.Type.SpecialType == SpecialType.System_Boolean) { writer.Write("System.CsScala.BooleanToString("); Core.Write(writer, e); writer.Write(")"); } else { Core.Write(writer, e); } }; write(left); writer.Write(" "); writer.Write(operatorToken.ToString()); writer.Write(" "); write(right); } }
public static void Go(ScalaWriter writer, MemberAccessExpressionSyntax expression) { var model = Program.GetModel(expression); var memberName = expression.Name.Identifier.ValueText; var type = model.GetTypeInfo(expression.Expression).ConvertedType; var typeStr = TypeProcessor.GenericTypeName(type); if (expression.Expression is PredefinedTypeSyntax) { if (memberName == "MaxValue" || memberName == "MinValue" || memberName == "NaN") { var predefined = expression.Expression.ToString(); if (predefined.StartsWith("u")) { //Scala does not have unsigned types. Forward these to CsScala writer.Write("System.CsScala."); writer.Write(predefined); writer.Write(memberName); } else { writer.Write(predefined[0].ToString().ToUpper()); writer.Write(predefined.Substring(1)); writer.Write("."); writer.Write(memberName); } } else { var field = System.Type.GetType(typeStr).GetField(memberName); if (field == null) { throw new Exception("Cannot use " + memberName + " as a field. If you're passing a function, wrap a closure around it. " + Utility.Descriptor(expression)); } var val = field.GetValue(null); if (val is string) { writer.Write("\"" + val + "\""); } else { writer.Write(val.ToString()); } } } else if (type.OriginalDefinition is INamedTypeSymbol && type.OriginalDefinition.As <INamedTypeSymbol>().SpecialType == SpecialType.System_Nullable_T) { switch (memberName) { case "HasValue": writer.Write("("); WriteMember(writer, expression.Expression); writer.Write(" != null)"); break; case "Value": var nullableType = TypeProcessor.ConvertType(type.As <INamedTypeSymbol>().TypeArguments.Single()); WriteMember(writer, expression.Expression); if (TypeProcessor.IsPrimitiveType(nullableType)) { writer.Write("."); writer.Write(nullableType[0].ToString().ToLower()); writer.Write(nullableType.Substring(1)); writer.Write("Value()"); } break; default: throw new Exception("Need handler for Nullable." + memberName + " " + Utility.Descriptor(expression)); } } else { var translate = PropertyTranslation.Get(typeStr, memberName); if (translate != null && translate.ExtensionMethod != null) { writer.Write(translate.ExtensionMethod); writer.Write("("); if (!(model.GetSymbolInfo(expression.Expression).Symbol is INamedTypeSymbol)) { Core.Write(writer, expression.Expression); } writer.Write(")"); return; } if (translate != null) { memberName = translate.ReplaceWith; } else { memberName = WriteIdentifierName.TransformIdentifier(memberName); } if (type != null) //if type is null, then we're just a namespace. We can ignore these. { WriteMember(writer, expression.Expression); writer.Write("."); } 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.ConvertTypeWithColon(g)); } writer.Write("]"); } } }