private void HandleTopLevelStatement(PythonScript script, Statement statement, StringBuilder declarations, Dictionary <string, GuessedType> declaredFields) { if (statement.Start.Line > _currentLine) { if (TryGetComments(script, _currentLine, statement.Start.Line, out var comments)) { declarations.AppendLine(comments); } } _currentLine = statement.End.Line; // Top level statements need special treatment if (statement is FunctionDefinition functionDefinition) { HandleFunctionDeclaration( script, declarations, declaredFields, functionDefinition); } else if (statement is AssignmentStatement assignmentStatement) { // We have to guess the type of the right hand side to continue var rightExpression = assignmentStatement.Right; foreach (var leftExpression in assignmentStatement.Left) { if (!(leftExpression is NameExpression nameExpression)) { continue; } // Assignments to __all__ can be ignored. We could use them to know what is public, // But it applies to a miniscule set of modules anyway if (nameExpression.Name == "__all__") { continue; } string managedFieldType; GuessedType fieldType; var expressionConverter = new ExpressionConverter(script, _typings, _modules); if (rightExpression is DictionaryExpression dictionaryExpression) { expressionConverter.GetDictionaryTypes(dictionaryExpression, out _, out _, out managedFieldType); fieldType = GuessedType.Unknown; } else if (rightExpression is ListExpression listExpression) { expressionConverter.GetListType(listExpression, out var valueType, out managedFieldType); if (valueType == GuessedType.Object) { fieldType = GuessedType.ObjectList; } else { fieldType = GuessedType.UnknownList; } } else { fieldType = expressionConverter.GetExpressionType(rightExpression); managedFieldType = TypeMapping.GuessManagedType(fieldType); } declarations.Append("private static readonly "); declarations.Append(managedFieldType); declarations.Append(' '); declarations.Append(nameExpression.Name); declarations.Append(" = "); declarations.Append(ConvertExpression(script, rightExpression)); declarations.AppendLine(";"); declaredFields[nameExpression.Name] = fieldType; } } else if (statement is ExpressionStatement expressionStatement) { if (expressionStatement.Expression is ConstantExpression constantExpression) { // Top level expressions of type string are documentation statements var value = constantExpression.Value; if (value is string stringValue) { foreach (var commentLine in stringValue.Split("\n")) { declarations.AppendLine("//" + commentLine); } } else { Debugger.Break(); } } else { declarations.AppendLine("FIXME"); var exprConverter = new ExpressionConverter(script, _typings, _modules); exprConverter.AddVariables(declaredFields); // Ensure that globally defined fields are known statement.Walk(exprConverter); declarations.Append(exprConverter.Result.ToString()); } } else if (statement is FromImportStatement || statement is ImportStatement) { // Ignore these since we're already taking care of it via the dependencies / modules } else if (statement is SuiteStatement suiteStatement) { foreach (var subStatement in suiteStatement.Statements) { HandleTopLevelStatement(script, subStatement, declarations, declaredFields); } } else { declarations.AppendLine("FIXME"); var exprConverter = new ExpressionConverter(script, _typings, _modules); statement.Walk(exprConverter); declarations.Append(exprConverter.Result.ToString()); } }