public static void Go(HaxeWriter writer, FieldDeclarationSyntax field) { foreach (var declaration in field.Declaration.Variables) { Go(writer, field.Modifiers, declaration.Identifier.ValueText, field.Declaration.Type, declaration.Initializer); } }
public static void Go(HaxeWriter writer, LockStatementSyntax statement) { if (statement.DescendantNodes().OfType <ReturnStatementSyntax>().Any()) { throw new Exception("Cannot return from within a lock statement " + Utility.Descriptor(statement)); } writer.WriteIndent(); writer.Write("CsLock.Lock("); Core.Write(writer, statement.Expression); writer.Write(", function()\r\n"); writer.WriteOpenBrace(); if (statement.Statement is BlockSyntax) { foreach (var s in statement.Statement.As <BlockSyntax>().Statements) { Core.Write(writer, s); } } else { Core.Write(writer, statement.Statement); } writer.Indent--; writer.WriteIndent(); writer.Write("});\r\n"); }
private static void Go(HaxeWriter writer, ExpressionSyntax array, InitializerExpressionSyntax initializer) { writer.Write("[ "); bool first = true; if (initializer != null) { foreach (var expression in initializer.Expressions) { if (first) { first = false; } else { writer.Write(", "); } Core.Write(writer, expression); } } writer.Write(" ]"); }
public static void Go(HaxeWriter writer, LiteralExpressionSyntax expression) { var str = expression.ToString(); if (str.StartsWith("@")) str = "\"" + str.RemoveFromStartOfString("@\"").RemoveFromEndOfString("\"").Replace("\\", "\\\\").Replace("\"\"", "\\\"") + "\""; if (str.StartsWith("'") && str.EndsWith("'")) { //chars just get written as integers str = str.Substring(1, str.Length - 2); if (str.StartsWith("\\")) str = str.Substring(1); if (str.Length != 1) throw new Exception("Unexpected char string: " + str); str = ((int)str[0]).ToString(); } if (str.EndsWith("f") && !str.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) str = str.Substring(0, str.Length - 1); writer.Write(str); }
public static void Go(HaxeWriter writer, BinaryExpressionSyntax expression) { //check for invocation of overloaded operator var symbolInfo = Program.GetModel(expression).GetSymbolInfo(expression); var method = symbolInfo.Symbol as IMethodSymbol; if (IsOverloadedOperator(expression, method)) { WriteOverloadedOperatorInvocation(writer, expression, method); return; } //Check for integer division. Integer division is handled automatically in C#, but must be explicit in haxe. if (expression.OperatorToken.Kind() == SyntaxKind.SlashToken && Program.GetModel(expression).GetTypeInfo(expression).Type.SpecialType == SpecialType.System_Int32) { //If parent is a cast to int, skip this step. This isn't necessary for correctness, but it makes cleaner code. var castIsExplicit = expression.Parent is ParenthesizedExpressionSyntax && expression.Parent.Parent is CastExpressionSyntax && expression.Parent.Parent.As <CastExpressionSyntax>().Type.ToString() == "int"; if (!castIsExplicit) { writer.Write("Std.int("); Go(writer, expression.Left, expression.OperatorToken, expression.Right); writer.Write(")"); return; } } Go(writer, expression.Left, expression.OperatorToken, expression.Right); }
/// <summary> /// calls to Enum.Parse get re-written as calls to our special Parse methods on each enum. We assume the first parameter to Enum.Parse is a a typeof() /// </summary> private static void WriteEnumParse(HaxeWriter writer, InvocationExpressionSyntax invocationExpression) { var args = invocationExpression.ArgumentList.Arguments; if (args.Count < 2 || args.Count > 3) { throw new Exception("Expected 2-3 args to Enum.Parse"); } if (args.Count == 3 && (!(args[2].Expression is LiteralExpressionSyntax) || args[2].Expression.As <LiteralExpressionSyntax>().ToString() != "false")) { throw new NotImplementedException("Case-insensitive Enum.Parse is not supported " + Utility.Descriptor(invocationExpression)); } if (!(args[0].Expression is TypeOfExpressionSyntax)) { throw new Exception("Expected a typeof() expression as the first parameter of Enum.Parse " + Utility.Descriptor(invocationExpression)); } var type = Program.GetModel(invocationExpression).GetTypeInfo(args[0].Expression.As <TypeOfExpressionSyntax>().Type).Type; writer.Write(type.ContainingNamespace.FullNameWithDot().ToLower()); writer.Write(WriteType.TypeName((INamedTypeSymbol)type)); writer.Write(".Parse("); Core.Write(writer, args[1].Expression); writer.Write(")"); }
public static void Go(HaxeWriter writer, SyntaxTokenList modifiers, string name, TypeSyntax type, EqualsValueClauseSyntax initializerOpt = null) { writer.WriteIndent(); var isConst = IsConst(modifiers, initializerOpt, type); WriteFieldModifiers(writer, modifiers); if (isConst) { writer.Write("inline "); } writer.Write("var "); writer.Write(name); writer.Write(TypeProcessor.ConvertTypeWithColon(type)); if (isConst) { writer.Write(" = "); Core.Write(writer, initializerOpt.Value); } writer.Write(";"); writer.WriteLine(); }
public static void Go(HaxeWriter writer, ForEachStatementSyntax foreachStatement) { writer.WriteIndent(); writer.Write("for ("); writer.Write(foreachStatement.Identifier.ValueText); writer.Write(" in "); WriteEnumerator(writer, foreachStatement.Expression, Program.GetModel(foreachStatement).GetTypeInfo(foreachStatement.Expression).Type, false); writer.Write(")\r\n"); writer.WriteOpenBrace(); if (foreachStatement.Statement is BlockSyntax) { foreach (var statement in foreachStatement.Statement.As <BlockSyntax>().Statements) { Core.Write(writer, statement); } } else { Core.Write(writer, foreachStatement.Statement); } writer.WriteCloseBrace(); }
public static void Go(HaxeWriter writer, ConditionalExpressionSyntax expression) { Core.Write(writer, expression.Condition); writer.Write(" ? "); Core.Write(writer, expression.WhenTrue); writer.Write(" : "); Core.Write(writer, expression.WhenFalse); }
public static void Go(HaxeWriter writer, ElementAccessExpressionSyntax expression) { Core.Write(writer, expression.Expression); var typeHaxe = TypeProcessor.ConvertType(Program.GetModel(expression).GetTypeInfo(expression.Expression).ConvertedType); if (typeHaxe.StartsWith("Array<")) //arrays are the only thing haxe allows using the [] syntax with { if (expression.ArgumentList.Arguments.Count != 1) { throw new Exception("Expect array index to have a single argument " + Utility.Descriptor(expression)); } writer.Write("["); Core.Write(writer, expression.ArgumentList.Arguments.Single().Expression); writer.Write("]"); } else if (typeHaxe == "haxe.io.Bytes") { writer.Write(".get("); Core.Write(writer, expression.ArgumentList.Arguments.Single().Expression); writer.Write(")"); } else if (typeHaxe == "String") { //indexing into string to get its character results in a call to charCodeAt writer.Write(".charCodeAt("); Core.Write(writer, expression.ArgumentList.Arguments.Single().Expression); writer.Write(")"); } else { writer.Write(".GetValue"); var symbol = Program.GetModel(expression).GetSymbolInfo(expression).Symbol.OriginalDefinition.As <IPropertySymbol>(); writer.Write(string.Join("", symbol.Parameters.ToArray().Select(o => "_" + o.Type.Name))); writer.Write("("); bool first = true; foreach (var arg in expression.ArgumentList.Arguments) { if (first) { first = false; } else { writer.Write(", "); } Core.Write(writer, arg.Expression); } writer.Write(")"); } }
private static void WriteCastOperator(HaxeWriter writer, CastExpressionSyntax expression, IMethodSymbol symbol, string destTypeHaxe) { writer.Write(TypeProcessor.ConvertType(symbol.ContainingType)); writer.Write(".op_Explicit_"); writer.Write(destTypeHaxe.TrySubstringBeforeFirst('<').Replace('.', '_')); writer.Write("("); Core.Write(writer, expression.Expression); writer.Write(")"); }
public static void WriteBlock(HaxeWriter writer, BlockSyntax block) { writer.WriteOpenBrace(); foreach (var statement in block.Statements) { Write(writer, statement); } writer.WriteCloseBrace(); }
public void Write(HaxeWriter writer) { if (this.StringOpt != null) { writer.Write(this.StringOpt); } else { Core.Write(writer, this.ArgumentOpt.Expression); } }
public static void Go(HaxeWriter writer, ConstructorDeclarationSyntax constructor) { if (constructor.Modifiers.Any(SyntaxKind.StaticKeyword)) { WriteStaticConstructor(writer, constructor); } else { WriteInstanceConstructor(writer, constructor); } }
private static void WriteOverloadedOperatorInvocation(HaxeWriter writer, BinaryExpressionSyntax expression, IMethodSymbol method) { writer.Write(method.ContainingType.ContainingNamespace.FullNameWithDot().ToLower()); writer.Write(method.ContainingType.Name); writer.Write("."); writer.Write(OverloadResolver.MethodName(method)); writer.Write("("); Core.Write(writer, expression.Left); writer.Write(", "); Core.Write(writer, expression.Right); writer.Write(")"); }
public static void Go(HaxeWriter writer, IEnumerable <EnumMemberDeclarationSyntax> allChildren) { int nextEnumValue = 0; var values = allChildren.Select(o => new { Syntax = o, Value = DetermineEnumValue(o, ref nextEnumValue) }).ToList(); foreach (var value in values) { writer.WriteLine("public static inline var " + value.Syntax.Identifier.ValueText + ":Int = " + value.Value + ";"); } writer.WriteLine(); writer.WriteLine("public static function ToString(e:Int):String"); writer.WriteOpenBrace(); writer.WriteLine("switch (e)"); writer.WriteOpenBrace(); foreach (var value in values) { writer.WriteLine("case " + value.Value + ": return \"" + value.Syntax.Identifier.ValueText + "\";"); } writer.WriteLine("default: return Std.string(e);"); writer.WriteCloseBrace(); writer.WriteCloseBrace(); writer.WriteLine(); writer.WriteLine("public static function Parse(s:String):Int"); writer.WriteOpenBrace(); writer.WriteLine("switch (s)"); writer.WriteOpenBrace(); foreach (var value in values) { writer.WriteLine("case \"" + value.Syntax.Identifier.ValueText + "\": return " + value.Value + ";"); } writer.WriteLine("default: throw new InvalidOperationException(s);"); writer.WriteCloseBrace(); writer.WriteCloseBrace(); writer.WriteLine(); writer.WriteLine("public static function Values():Array<Int>"); writer.WriteOpenBrace(); writer.WriteIndent(); writer.Write("return ["); writer.Write(string.Join(", ", values.Select(o => o.Value.ToString()))); writer.Write("];\r\n"); writer.WriteCloseBrace(); }
public static void WriteIndexerDeclaration(HaxeWriter writer, IndexerDeclarationSyntax decl) { foreach (var accessor in decl.AccessorList.Accessors) { writer.WriteIndent(); if (decl.Modifiers.Any(SyntaxKind.OverrideKeyword) || decl.Modifiers.Any(SyntaxKind.NewKeyword)) { writer.Write("override "); } if (decl.Modifiers.Any(SyntaxKind.PublicKeyword) || decl.Modifiers.Any(SyntaxKind.ProtectedKeyword) || decl.Modifiers.Any(SyntaxKind.InternalKeyword)) { writer.Write("public "); } if (decl.Modifiers.Any(SyntaxKind.PrivateKeyword)) { writer.Write("private "); } var isGet = accessor.Kind() == SyntaxKind.GetAccessorDeclaration; writer.Write("function "); writer.Write(isGet ? "Get" : "Set"); writer.Write("Value_"); writer.Write(Program.GetModel(decl).GetTypeInfo(decl.ParameterList.Parameters.Single().Type).Type.Name); writer.Write("("); foreach (var prm in decl.ParameterList.Parameters) { writer.Write(prm.Identifier.ValueText); writer.Write(TypeProcessor.ConvertTypeWithColon(prm.Type)); } if (isGet) { writer.Write(")"); writer.Write(TypeProcessor.ConvertTypeWithColon(decl.Type)); } else { writer.Write(", value"); writer.Write(TypeProcessor.ConvertTypeWithColon(decl.Type)); writer.Write("):Void"); } writer.WriteLine(); if (accessor.Body != null) { Core.Write(writer, accessor.Body); } } }
public static void Go(HaxeWriter writer, IdentifierNameSyntax identifier, bool byRef = false) { writer.Write(identifier.ToString()); if (!byRef) { var symbol = Program.GetModel(identifier).GetSymbolInfo(identifier).Symbol; if (Program.RefOutSymbols.ContainsKey(symbol)) { writer.Write(".Value"); } } }
private static void WriteEnumGetValues(HaxeWriter writer, InvocationExpressionSyntax invocationExpression) { if (!(invocationExpression.ArgumentList.Arguments[0].Expression is TypeOfExpressionSyntax)) { throw new Exception("Expected a typeof() expression as the first parameter of Enum.GetValues " + Utility.Descriptor(invocationExpression)); } var type = Program.GetModel(invocationExpression).GetTypeInfo(invocationExpression.ArgumentList.Arguments[0].Expression.As <TypeOfExpressionSyntax>().Type).Type; writer.Write(type.ContainingNamespace.FullNameWithDot().ToLower()); writer.Write(WriteType.TypeName((INamedTypeSymbol)type)); writer.Write(".Values()"); }
public static void Go(HaxeWriter writer, LocalDeclarationStatementSyntax declaration) { foreach (var variable in declaration.Declaration.Variables) { var symbol = Program.GetModel(declaration).GetDeclaredSymbol(variable); var isRef = UsedAsRef(variable, symbol); writer.WriteIndent(); writer.Write("var "); writer.Write(variable.Identifier.ValueText); if (isRef) { var typeStr = TypeProcessor.ConvertType(declaration.Declaration.Type); writer.Write(":CsRef<"); writer.Write(typeStr); writer.Write(">"); Program.RefOutSymbols.TryAdd(symbol, null); writer.Write(" = new CsRef<"); writer.Write(typeStr); writer.Write(">("); if (variable.Initializer == null) { writer.Write(TypeProcessor.DefaultValue(typeStr)); } else { Core.Write(writer, variable.Initializer.As <EqualsValueClauseSyntax>().Value); } writer.Write(")"); } else { writer.Write(TypeProcessor.ConvertTypeWithColon(declaration.Declaration.Type)); if (variable.Initializer != null) { writer.Write(" = "); Core.Write(writer, variable.Initializer.As <EqualsValueClauseSyntax>().Value); } } writer.Write(";\r\n"); } }
public static void Go(HaxeWriter writer, ReturnStatementSyntax statement) { writer.WriteIndent(); writer.Write("return"); if (statement.Expression != null) { writer.Write(" "); Core.Write(writer, statement.Expression); } writer.Write(";\r\n"); }
public static void WriteFieldModifiers(HaxeWriter writer, SyntaxTokenList modifiers) { if (modifiers.Any(SyntaxKind.PublicKeyword) || modifiers.Any(SyntaxKind.ProtectedKeyword) || modifiers.Any(SyntaxKind.InternalKeyword)) { writer.Write("public "); } if (modifiers.Any(SyntaxKind.PrivateKeyword)) { writer.Write("private "); } if (modifiers.Any(SyntaxKind.StaticKeyword) || modifiers.Any(SyntaxKind.ConstKeyword)) { writer.Write("static "); } }
private static void Go(HaxeWriter writer, IEnumerable <ParameterSyntax> parameters, SyntaxNode body, TypeInfo type) { var methodSymbol = type.ConvertedType.As <INamedTypeSymbol>().DelegateInvokeMethod.As <IMethodSymbol>(); writer.Write("function ("); for (int pi = 0; pi < parameters.Count(); pi++) { var parameter = parameters.ElementAt(pi); if (pi > 0) { writer.Write(", "); } writer.Write(parameter.Identifier.ValueText); if (parameter.Type != null) { writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type)); } else { writer.Write(TypeProcessor.ConvertTypeWithColon(methodSymbol.Parameters[pi].Type)); } } writer.Write(")"); writer.Write(TypeProcessor.ConvertTypeWithColon(methodSymbol.ReturnType)); if (body is BlockSyntax) { writer.Write("\r\n"); Core.Write(writer, body); writer.WriteIndent(); } else { writer.Write(" { "); if (methodSymbol.ReturnsVoid == false) { writer.Write("return "); } Core.Write(writer, body); writer.Write("; } "); } }
public static void Go(HaxeWriter writer, IfStatementSyntax ifStatement, bool indent = true) { if (indent) { writer.WriteIndent(); } writer.Write("if ("); Core.Write(writer, ifStatement.Condition); writer.Write(")\r\n"); if (ifStatement.Statement is BlockSyntax) { Core.Write(writer, ifStatement.Statement); } else { writer.WriteOpenBrace(); Core.Write(writer, ifStatement.Statement); writer.WriteCloseBrace(); } if (ifStatement.Else != null) { writer.WriteIndent(); writer.Write("else"); if (ifStatement.Else.Statement is BlockSyntax) { writer.Write("\r\n"); Core.Write(writer, ifStatement.Else.Statement); } else if (ifStatement.Else.Statement is IfStatementSyntax) { writer.Write(" "); WriteIfStatement.Go(writer, ifStatement.Else.Statement.As <IfStatementSyntax>(), false); } else { writer.Write("\r\n"); writer.WriteOpenBrace(); Core.Write(writer, ifStatement.Else.Statement); writer.WriteCloseBrace(); } } }
public static void Go(HaxeWriter writer, UsingStatementSyntax usingStatement) { if (usingStatement.DescendantNodes().OfType <ReturnStatementSyntax>().Any()) { throw new Exception("CS2HX does not support returning from within a using block. " + Utility.Descriptor(usingStatement)); } var expression = usingStatement.Expression; //if (expression is ExpressionStatement) // expression = expression.As<ExpressionStatement>().Expression; //Ensure the using statement is a local variable - we can't deal with things we can't reliably repeat in the finally block var resource = Utility.TryGetIdentifier(expression); if (resource == null) { throw new Exception("Using statements must reference a local variable. " + Utility.Descriptor(usingStatement)); } writer.WriteLine("var __disposed_" + resource + ":Bool = false;"); writer.WriteLine("try"); writer.WriteOpenBrace(); if (usingStatement.Statement is BlockSyntax) { foreach (var s in usingStatement.Statement.As <BlockSyntax>().Statements) { Core.Write(writer, s); } } else { Core.Write(writer, usingStatement.Statement); } writer.WriteLine("__disposed_" + resource + " = true;"); writer.WriteLine(resource + ".Dispose();"); writer.WriteCloseBrace(); writer.WriteLine("catch (__catch_" + resource + ":Dynamic)"); writer.WriteOpenBrace(); writer.WriteLine("if (!__disposed_" + resource + ")"); writer.WriteLine(" " + resource + ".Dispose();"); writer.WriteLine("throw __catch_" + resource + ";"); writer.WriteCloseBrace(); }
public static void Go(HaxeWriter writer, IdentifierNameSyntax identifier, bool byRef = false) { writer.Write(identifier.ToString()); if (!byRef) { var symbol = Program.GetModel(identifier).GetSymbolInfo(identifier).Symbol; if (symbol == null) { throw new Exception("Symbol could not be resolved. Are you sure the C# is valid? " + Utility.Descriptor(identifier)); } if (Program.RefOutSymbols.ContainsKey(symbol)) { writer.Write(".Value"); } } }
public static void WriteConstructorsHelper(IEnumerable <INamedTypeSymbol> allTypes, string nameArg) { foreach (var t in allTypes.Select(o => o.ContainingNamespace.FullNameWithDot().ToLower() + WriteType.TypeName(o))) { AllTypes.Add(t); } var name = string.IsNullOrWhiteSpace(nameArg) ? "Constructors" : nameArg; using (var writer = new HaxeWriter("", name)) { writer.WriteLine(@"/* This file serves two purposes: 1) It imports every type that CS2HX generated. haXe will ignore any types that aren't used by haXe code, so this ensures haXe compiles all of your code. 2) It lists all the static constructors. haXe doesn't have the concept of static constructors, so CS2HX generated cctor() methods. You must call these manually. If you call Constructors.init(), all static constructors will be called at once. */ package ;"); foreach (var type in AllTypes.OrderBy(o => o)) { writer.WriteLine("import " + type + ";"); } writer.WriteLine("import system.TimeSpan;"); writer.WriteLine("class " + name); writer.WriteOpenBrace(); writer.WriteLine("public static function init()"); writer.WriteOpenBrace(); writer.WriteLine("TimeSpan.cctor();"); foreach (var cctor in StaticConstructors.OrderBy(o => o)) { writer.WriteLine(cctor + ".cctor();"); } writer.WriteCloseBrace(); writer.WriteCloseBrace(); } }
public static void Go(HaxeWriter writer, EventFieldDeclarationSyntax node) { throw new Exception("Events are not supported " + Utility.Descriptor(node)); /* * foreach (var declaration in node.Declaration.Variables) * { * * writer.WriteIndent(); * WriteField.WriteFieldModifiers(writer, node.Modifiers); * writer.Write("var "); * writer.Write(declaration.Identifier.ValueText); * writer.Write(":CsEvent<"); * writer.Write(TypeProcessor.ConvertType(node.Declaration.Type)); * writer.Write(">;\r\n"); * }*/ }
public static void Go(HaxeWriter writer, ArrayCreationExpressionSyntax array) { if (array.Type.RankSpecifiers.Count > 1) { throw new Exception("Multi-dimensional arrays are not supported"); } if (array.Type.ElementType.ToString() == "byte") { writer.Write("haxe.io.Bytes.alloc("); Core.Write(writer, array.Type.RankSpecifiers[0].Sizes[0]); writer.Write(")"); } else { Go(writer, array, array.Initializer); } }
public static void Go(HaxeWriter writer, BreakStatementSyntax statement) { //Traverse up to figure out what we're breaking from. If we're breaking from a loop, it's fine. However, if we're breaking from a switch statement, throw an error as haxe doesn't allow this. var breakingFrom = statement.Parent; while (!(breakingFrom is WhileStatementSyntax || breakingFrom is ForStatementSyntax || breakingFrom is DoStatementSyntax || breakingFrom is ForEachStatementSyntax)) { if (breakingFrom is SwitchStatementSyntax) { throw new Exception("Cannot \"break\" from within a switch statement. " + Utility.Descriptor(statement)); } breakingFrom = breakingFrom.Parent; } writer.WriteLine("break;"); }