private static void WriteOneDelegate(OutputWriter outputWriter, Context.DelegateSyntaxAndSymbol first, bool fileExists)
        {
            Context.Instance.Namespace = first.Symbol.ContainingNamespace.FullName();
            Context.Instance.Type = first.Symbol;
            TypeProcessor.ClearUsedTypes();
            var mynamespace = Context.Instance.Type.ContainingNamespace.FullName().RemoveFromEndOfString(".Namespace");
            // + "." + TypeState.Instance.TypeName;

            var myUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(mynamespace));
            var SystemUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System"));
            // Required as certain functions like boxing are in this namespace
            Context.Instance.UsingDeclarations =
                first.Syntax.Parent.DescendantNodes().OfType<UsingDirectiveSyntax>().ToArray()
                    .Union(new[]
                    {
                        myUsingDirective, SystemUsingDirective
                    }).ToArray();
            OutputWriter writer = null;

            using (
                writer =
                    outputWriter == null
                        ? new OutputWriter(Context.Instance.Namespace, Context.Instance.TypeName)
                        : new TempWriter())
            {

                if (outputWriter != null)
                {
                    writer.WriteLine();
                    writer.Indent = outputWriter.Indent + 2;
                    writer.WriteIndent();
                }

                writer.FileExists = fileExists;

                WriteBcl.Go(writer);

                WriteStandardIncludes.Go(writer);

                //Look for generic arguments 
              
                {
                    List<TypeParameterSyntax> genericArgs = new List<TypeParameterSyntax>();
                    if (first.Syntax.TypeParameterList != null)
                        genericArgs = first.Syntax.TypeParameterList.Parameters.ToList();

                    var name = WriteType.TypeName(Context.Instance.Type, false); //Context.Instance.TypeName;

                    if (genericArgs.Count > 0)
                    {
                        name = "template " + name;
                        name += ("(");
                        name += (string.Join(" , ", genericArgs.Select(o => o)));
                        name += (")");

                        writer.WriteLine(name);

                        writer.OpenBrace();

                        writer.WriteLine("alias __Delegate!(" + TypeProcessor.ConvertType(first.Syntax.ReturnType) + " delegate" +
                                         WriteMethod.GetParameterListAsString(first.Syntax.ParameterList.Parameters) + ") " +
                                         WriteType.TypeName(Context.Instance.Type, false) + ";");

                        writer.CloseBrace();
                    }
                    else
                    {
                        //Non-generic
                        writer.WriteLine("alias __Delegate!(" + TypeProcessor.ConvertType(first.Syntax.ReturnType) + " delegate" +
                                         WriteMethod.GetParameterListAsString(first.Syntax.ParameterList.Parameters) + ") " +
                                         WriteType.TypeName(Context.Instance.Type, false) + ";");
                    }
                }

                if (outputWriter != null)
                    outputWriter.WriteLine(writer.ToString());
            }
        }
 public static void Update(Compilation compilation)
 {
     Instance = new Context();
     if (compilation != null)
         Instance.UpdateContext(compilation);
 }
 internal static void Pop()
 {
     Instance = Instances.Pop();
 }
        private static void WriteOutNestedTypes(Context.SyntaxAndSymbol first, OutputWriter writer)
        {
            //WriteOut All My nested classes
            Context.Push();

            var delegates = first.Syntax.DescendantNodes().OfType<DelegateDeclarationSyntax>()
                .Select(o => new
            {
                Syntax = o,
                Symbol = TypeProcessor.GetDeclaredSymbol(o),
                TypeName = WriteType.TypeName((INamedTypeSymbol)TypeProcessor.GetDeclaredSymbol(o))
            }).Where(k => k.Symbol.ContainingType == Context.Instance.Type) // Ignore all nested delegates
                .GroupBy(o => o.Symbol.ContainingNamespace.FullNameWithDot() + o.TypeName)
                .ToList();


            delegates.ForEach(type => //.ForEach(type => //.Parallel(type =>
            {
                Context.Instance = new Context
                {
                    TypeName = type.First().TypeName,
                    DelegatePartials =
                        type.Select(
                            o =>
                                new Context.DelegateSyntaxAndSymbol
                    {
                        Symbol = (INamedTypeSymbol)o.Symbol,
                        Syntax = o.Syntax
                    })
                            .Where(o => !Program.DoNotWrite.ContainsKey(o.Syntax))
                            .ToList()
                };

                if (Context.Instance.DelegatePartials.Count > 0)
                    WriteDelegate.Go(writer);
            });
            Context.Pop();

            Context.Push();
            var subclasses = first.Syntax.DescendantNodes().OfType<BaseTypeDeclarationSyntax>()
                .Select(o => new
            {
                Syntax = o,
                Symbol = TypeProcessor.GetDeclaredSymbol(o),
                TypeName = WriteType.TypeName((INamedTypeSymbol)TypeProcessor.GetDeclaredSymbol(o))
            }).Where(k => k.Symbol.ContainingType == Context.Instance.Type) // Ignore all nested classes
                .GroupBy(o => o.Symbol.ContainingNamespace.FullNameWithDot() + o.TypeName)
                .ToList();

            subclasses.ForEach(type => //.ForEach(type => //.Parallel(type =>
            {
                Context.Instance = new Context
                {
                    TypeName = type.First().TypeName,
                    Partials =
                        type.Select(
                            o =>
                                new Context.SyntaxAndSymbol
                    {
                        Symbol = (INamedTypeSymbol)o.Symbol,
                        Syntax = o.Syntax
                    })
                            .Where(o => !Program.DoNotWrite.ContainsKey(o.Syntax))
                            .ToList()
                };

                if (Context.Instance.Partials.Count > 0)
                {
                    try
                    {
                        WriteType.Go(writer);
                    }
                    catch (Exception ex)
                    {
                        //TODO: remove this when done with CorLib 
                        throw ex;
                    }
                }
            });

            Context.Pop();
        }
        private static IEnumerable<MemberDeclarationSyntax> WriteFields(List<MemberDeclarationSyntax> membersToWrite, Context.SyntaxAndSymbol first, OutputWriter writer)
        {
            var fields = membersToWrite.OfType<FieldDeclarationSyntax>().ToList();
            var nonFields = membersToWrite.Except(fields); // also static fields should be separately dealt with

            //Not needed anymore ... reflection takes care of this
            //if (fields.Count > 0 && fields.Any(j => j.GetModifiers().Any(SyntaxKind.ConstKeyword) ||
            //                                        j.GetModifiers().Any(SyntaxKind.StaticKeyword)))
            //{
            //    writer.WriteLine("enum __staticFieldTuple = __Tuple!(" +
            //                     fields.Where(
            //                         j =>
            //                             j.GetModifiers().Any(SyntaxKind.ConstKeyword) ||
            //                             j.GetModifiers().Any(SyntaxKind.StaticKeyword))
            //                         .Select(
            //                             k =>
            //                                 "\"" +
            //                                 WriteIdentifierName.TransformIdentifier(
            //                                     k.Declaration.Variables[0].Identifier.ValueText) + "\"")
            //                         .Aggregate((i, j) => i + "," + j) + ");//Reflection Support");
            //}

            var structLayout = first.Syntax.GetAttribute(Context.StructLayout);
            if (structLayout != null)
            {
                LayoutKind value = LayoutKind.Auto;
                if (
                    structLayout.ArgumentList.Arguments.Any(
                        k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "Value"))
                {
                    value =
                        (LayoutKind)
                            Enum.Parse(typeof(LayoutKind),
                                structLayout.ArgumentList.Arguments.FirstOrDefault(
                                    k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "Value")
                                    .Expression.ToFullString()
                                    .SubstringAfterLast('.'));
                }

                else if (structLayout.ArgumentList.Arguments.Count > 0 &&
                         structLayout.ArgumentList.Arguments[0].NameEquals == null)
                {
                    value =
                        (LayoutKind)
                            Enum.Parse(typeof(LayoutKind),
                                structLayout.ArgumentList.Arguments[0].Expression.ToFullString()
                                    .SubstringAfterLast('.'));
                }
                int pack = -1;
                int size = -1;
                CharSet charset = CharSet.Auto;
                //					if (structLayout.ArgumentList.Arguments.Count > 1)
                {
                    try
                    {
                        if (
                            structLayout.ArgumentList.Arguments.Any(
                                k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "CharSet"))
                        {
                            charset =
                                (CharSet)
                                    Enum.Parse(typeof(CharSet),
                                        structLayout.ArgumentList.Arguments.FirstOrDefault(
                                            k =>
                                                k.NameEquals != null &&
                                                k.NameEquals.Name.ToFullString().Trim() == "CharSet")
                                            .Expression.ToFullString()
                                            .SubstringAfterLast('.'));
                            //structLayout.ArgumentList.Arguments.Where (k => k.Expression is MemberAccessExpressionSyntax).FirstOrDefault(k=>(k.Expression as MemberAccessExpressionSyntax).Name.ToFullString() == "Value");
                        }
                        //structLayout.ArgumentList.Arguments.Where (k => k.Expression is MemberAccessExpressionSyntax).FirstOrDefault(k=>(k.Expression as MemberAccessExpressionSyntax).Name.ToFullString() == "Value");
                        else if (structLayout.ArgumentList.Arguments.Count > 1 &&
                                 structLayout.ArgumentList.Arguments[1].NameEquals == null)
                        {
                            charset =
                                (CharSet)
                                    Enum.Parse(typeof(CharSet),
                                        structLayout.ArgumentList.Arguments[1].Expression.ToFullString()
                                            .SubstringAfterLast('.'));
                        }
                    }
                    catch (Exception ex)
                    {
                    }

                    try
                    {
                        if (
                            structLayout.ArgumentList.Arguments.Any(
                                k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "Pack"))
                        {
                            pack =
                                int.Parse(
                                    structLayout.ArgumentList.Arguments.FirstOrDefault(
                                        k =>
                                            k.NameEquals != null &&
                                            k.NameEquals.Name.ToFullString().Trim() == "Pack")
                                        .Expression.ToFullString());
                        }
                        //structLayout.ArgumentList.Arguments.Where (k => k.Expression is MemberAccessExpressionSyntax).FirstOrDefault(k=>(k.Expression as MemberAccessExpressionSyntax).Name.ToFullString() == "Value");
                        else if (structLayout.ArgumentList.Arguments.Count > 2 &&
                                 structLayout.ArgumentList.Arguments[2].NameEquals == null)
                            pack = int.Parse(structLayout.ArgumentList.Arguments[2].Expression.ToFullString());
                    }
                    catch (Exception ex)
                    {
                    }

                    try
                    {
                        if (
                            structLayout.ArgumentList.Arguments.Any(
                                k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "Size"))
                        {
                            size =
                                int.Parse(
                                    structLayout.ArgumentList.Arguments.FirstOrDefault(
                                        k => k.NameColon != null && k.NameColon.ToFullString().Trim() == "Size")
                                        .Expression.ToFullString());
                        }
                        //structLayout.ArgumentList.Arguments.Where (k => k.Expression is MemberAccessExpressionSyntax).FirstOrDefault(k=>(k.Expression as MemberAccessExpressionSyntax).Name.ToFullString() == "Value");
                        else if (structLayout.ArgumentList.Arguments.Count > 3 &&
                                 structLayout.ArgumentList.Arguments[3].NameEquals == null)
                            size = int.Parse(structLayout.ArgumentList.Arguments[3].Expression.ToFullString());
                    }
                    catch (Exception ex)
                    {
                    }

                    //						size = int.Parse (structLayout.ArgumentList.Arguments [3].Expression.ToFullString ());
                }
                //					var pack = structLayout.ArgumentList.Arguments.FirstOrDefault (k => k.NameColon.Name.ToFullString() == "Pack");
                //					var charset = structLayout.ArgumentList.Arguments.FirstOrDefault (k => k.NameColon.Name.ToFullString() == "CharSet");
                //					var size = structLayout.ArgumentList.Arguments.FirstOrDefault (k => k.NameColon.Name.ToFullString() == "Size");

                if (value == LayoutKind.Explicit)
                {
                    var fieldGroups =
                        fields.GroupBy(f => f.GetAttribute(Context.FieldOffset).ArgumentList.Arguments[0].ToString())
                            .OrderBy(k => k.Key);
                    writer.Indent++;

                    foreach (var group in fieldGroups)
                    {
                        writer.WriteLine("//FieldOffset(" + @group.Key + ")");
                        writer.WriteLine("union {");
                        foreach (var member in @group)
                            Core.Write(writer, member);
                        writer.WriteLine("}");
                    }

                    //						foreach (var member in fields)
                    //						{
                    //							//                    writer.WriteLine();
                    //							Core.Write (writer, member);
                    //						}
                }
                else if (value == LayoutKind.Sequential)
                {
                    fields = SortFields(fields);

                    writer.Indent++;

                    foreach (var member in fields)
                    {
                        if (pack != -1)
                            writer.WriteLine("align (" + pack + "): //Pack = " + pack);
                        //                    writer.WriteLine();
                        Core.Write(writer, member);
                    }
                }

                else
                {
                    //Looks like C# aligns to 1 by default ... don't know about D...
                    fields = SortFields(fields);

                    writer.Indent++;
                    foreach (var member in fields)
                    {
                        pack = 1;
                        //TODO: on mac osx and mono this is required, on windows, it causes and issue
                        //                            writer.WriteLine("align (" + pack + "): //Pack = " + pack + " C# default");
                        //                    writer.WriteLine();
                        Core.Write(writer, member);
                    }
                }
            }
            else
            {
                //Looks like C# aligns to 1 by default ... don't know about D...
                fields = SortFields(fields);

                writer.Indent++;
                foreach (var member in fields)
                {
                    var pack = 1;
                    //TODO: on mac osx and mono this is required, on windows, it causes an issue (sizes are different)
                    //                        writer.WriteLine("align (" + pack + "): //Pack = " + pack + "C# default");
                    //                    writer.WriteLine();
                    Core.Write(writer, member);
                }
            }

            return nonFields;
        }
        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());
                }
            }
        }