From 210e79c903698644a8f17028b4a1fccfdee815a9 Mon Sep 17 00:00:00 2001 From: duckdoom5 Date: Thu, 27 Feb 2025 11:17:00 +0100 Subject: [PATCH] Temp --- src/AST/Class.cs | 10 + src/AST/Declaration.cs | 16 + src/CppParser/AST.cpp | 1 - src/CppParser/Bootstrap/Bootstrap.cs | 347 ++++++++++++++++-- .../Bootstrap/CodeGeneratorHelpers.cs | 243 +++++++++--- src/CppParser/Bootstrap/DeclCodeGenerators.cs | 221 +++++++++++ .../Bootstrap/InheritanceValidator.cs | 55 +++ .../Bootstrap/ParserCodeGenerators.cs | 104 ++++++ .../Bootstrap/Properties/launchSettings.json | 2 +- src/CppParser/Bootstrap/StmtCodeGenerators.cs | 24 +- src/CppParser/Bootstrap/TypeCodeGenerators.cs | 323 ++++++++++++++++ src/CppParser/Decl.h | 9 - src/CppParser/Types.h | 21 ++ src/Generator/Generators/CodeGenerator.cs | 4 +- 14 files changed, 1280 insertions(+), 100 deletions(-) create mode 100644 src/CppParser/Bootstrap/DeclCodeGenerators.cs create mode 100644 src/CppParser/Bootstrap/InheritanceValidator.cs create mode 100644 src/CppParser/Bootstrap/ParserCodeGenerators.cs create mode 100644 src/CppParser/Bootstrap/TypeCodeGenerators.cs diff --git a/src/AST/Class.cs b/src/AST/Class.cs index 442fe937..c2b41de3 100644 --- a/src/AST/Class.cs +++ b/src/AST/Class.cs @@ -274,6 +274,16 @@ namespace CppSharp.AST return Variables.FirstOrDefault(m => m.Name == name); } + public Property FindProperty(string name) + { + return Properties.FirstOrDefault(m => m.Name == name); + } + + public Field FindField(string name) + { + return Fields.FirstOrDefault(m => m.Name == name); + } + public override T Visit(IDeclVisitor visitor) { return visitor.VisitClassDecl(this); diff --git a/src/AST/Declaration.cs b/src/AST/Declaration.cs index 2fc50d31..c2107da9 100644 --- a/src/AST/Declaration.cs +++ b/src/AST/Declaration.cs @@ -223,6 +223,22 @@ namespace CppSharp.AST return namespaces; } + public DeclarationContext GetRootNamespace() + { + var currentNamespace = Namespace; + while (currentNamespace.Namespace != null) + currentNamespace = currentNamespace.Namespace; + + return currentNamespace; + } + + public void MoveToNamespace(DeclarationContext @namespace) + { + Namespace = @namespace; + OriginalNamespace?.Declarations.Remove(this); + Namespace?.Declarations.Add(this); + } + public string QualifiedName { get diff --git a/src/CppParser/AST.cpp b/src/CppParser/AST.cpp index e5823a23..6dc61151 100644 --- a/src/CppParser/AST.cpp +++ b/src/CppParser/AST.cpp @@ -1153,7 +1153,6 @@ namespace CppSharp { namespace CppParser { namespace AST { kind = DeclarationKind::TranslationUnit; } - TranslationUnit::~TranslationUnit() {} DEF_VECTOR(TranslationUnit, MacroDefinition*, Macros) NativeLibrary::NativeLibrary() diff --git a/src/CppParser/Bootstrap/Bootstrap.cs b/src/CppParser/Bootstrap/Bootstrap.cs index 916e7214..a42f27de 100644 --- a/src/CppParser/Bootstrap/Bootstrap.cs +++ b/src/CppParser/Bootstrap/Bootstrap.cs @@ -19,7 +19,7 @@ namespace CppSharp /// internal class Bootstrap : ILibrary { - private static bool CreatePatch = true; + private static bool CreatePatch = false; private static string OutputPath = CreatePatch ? "BootstrapPatch" : ""; private static string GetSourceDirectory(string dir) @@ -55,6 +55,7 @@ namespace CppSharp { driver.Options.GeneratorKind = GeneratorKind.CSharp; driver.Options.DryRun = true; + driver.ParserOptions.Verbose = true; driver.ParserOptions.EnableRTTI = true; driver.ParserOptions.LanguageVersion = LanguageVersion.CPP17_GNU; driver.ParserOptions.SkipLayoutInfo = true; @@ -80,10 +81,16 @@ namespace CppSharp module.Headers.AddRange(new[] { - "clang/AST/Stmt.h", - "clang/AST/StmtCXX.h", - "clang/AST/Expr.h", - "clang/AST/ExprCXX.h", + //"clang/AST/Stmt.h", + //"clang/AST/StmtCXX.h", + //"clang/AST/Expr.h", + //"clang/AST/ExprCXX.h", + "clang/AST/DeclBase.h", + "clang/AST/Decl.h", + "clang/AST/DeclCXX.h", + "clang/AST/DeclTemplate.h", + "clang/Basic/Builtins.h", + //"clang/AST/Type.h", }); module.LibraryDirs.Add(Path.Combine(llvmPath, "lib")); @@ -95,12 +102,18 @@ namespace CppSharp public void Preprocess(Driver driver, ASTContext ctx) { + CodeGeneratorHelpers.CppTypePrinter = new CppTypePrinter(driver.Context); + CodeGeneratorHelpers.CppTypePrinter.PushScope(TypePrintScopeKind.Local); + new IgnoreMethodsWithParametersPass { Context = driver.Context } .VisitASTContext(ctx); new GetterSetterToPropertyPass { Context = driver.Context } .VisitASTContext(ctx); new CheckEnumsPass { Context = driver.Context } .VisitASTContext(ctx); + new CleanCommentsPass { Context = driver.Context } + .VisitASTContext(ctx); + var preprocessDecls = new PreprocessDeclarations(); foreach (var unit in ctx.TranslationUnits) @@ -114,14 +127,13 @@ namespace CppSharp var exprClass = exprUnit.FindNamespace("clang").FindClass("Expr"); var exprSubclassVisitor = new SubclassVisitor(exprClass); exprUnit.Visit(exprSubclassVisitor); - exprCxxUnit.Visit(exprSubclassVisitor); + //exprCxxUnit.Visit(exprSubclassVisitor); ExprClasses = exprSubclassVisitor.Classes; - CodeGeneratorHelpers.CppTypePrinter = new CppTypePrinter(driver.Context); - CodeGeneratorHelpers.CppTypePrinter.PushScope(TypePrintScopeKind.Local); - - GenerateStmt(driver.Context); - GenerateExpr(driver.Context); + GenerateDecl(driver.Context); + //GenerateType(driver.Context); + //GenerateStmt(driver.Context); + //GenerateExpr(driver.Context); } public void Postprocess(Driver driver, ASTContext ctx) @@ -251,6 +263,262 @@ namespace CppSharp WriteFile(managedCodeGen, Path.Combine(OutputPath, "Parser", "ASTConverter.Stmt.cs")); } + private void GenerateType(BindingContext ctx) + { + var typeUnit = ctx.ASTContext.TranslationUnits.Find(unit => + unit.FileName.Contains("Type.h")); + var typeCxxUnit = ctx.ASTContext.TranslationUnits.Find(unit => + unit.FileName.Contains("CXXType.h")); + + var typeBaseClass = typeUnit.FindNamespace("clang").FindClass("Type"); + var typeSubclassVisitor = new SubclassVisitor(typeBaseClass); + typeUnit.Visit(typeSubclassVisitor); + typeCxxUnit?.Visit(typeSubclassVisitor); + + var types = typeSubclassVisitor.Classes; + + // Validate inheritance for types + var validator = new InheritanceValidator(); + validator.ValidateInheritance(types); + + // Write the native declarations headers + var declsCodeGen = new TypeDeclarationsCodeGenerator(ctx, types); + declsCodeGen.GenerateDeclarations(); + WriteFile(declsCodeGen, Path.Combine(OutputPath, "CppParser", "Type.h")); + + var defsCodeGen = new TypeDefinitionsCodeGenerator(ctx, types); + defsCodeGen.GenerateDefinitions(); + WriteFile(defsCodeGen, Path.Combine(OutputPath, "CppParser", "Type.cpp")); + + // Write the native parsing routines + var parserCodeGen = new TypeParserCodeGenerator(ctx, types); + parserCodeGen.GenerateParser(); + WriteFile(parserCodeGen, Path.Combine(OutputPath, "CppParser", "ParseType.cpp")); + + // Write the managed declarations + var managedCodeGen = new ManagedParserCodeGenerator(ctx, types); + managedCodeGen.GenerateDeclarations(); + WriteFile(managedCodeGen, Path.Combine(OutputPath, "AST", "Type.cs")); + + managedCodeGen = new TypeASTConverterCodeGenerator(ctx, types); + managedCodeGen.Process(); + WriteFile(managedCodeGen, Path.Combine(OutputPath, "Parser", "ASTConverter.Type.cs")); + } + + + private void GenerateDecl(BindingContext ctx) + { + var declBaseUnit = ctx.ASTContext.TranslationUnits.Find(unit => + unit.FileName.Contains("DeclBase.h")); + var declUnit = ctx.ASTContext.TranslationUnits.Find(unit => + unit.FileName.Contains("Decl.h")); + var declTemplateUnit = ctx.ASTContext.TranslationUnits.Find(unit => + unit.FileName.Contains("DeclTemplate.h")); + var declCxxUnit = ctx.ASTContext.TranslationUnits.Find(unit => + unit.FileName.Contains("DeclCXX.h")); + + var declClass = declBaseUnit.FindClass("clang::Decl"); + var declSubclassVisitor = new SubclassVisitor(declClass); + declBaseUnit.Visit(declSubclassVisitor); + declUnit.Visit(declSubclassVisitor); + declCxxUnit.Visit(declSubclassVisitor); + declTemplateUnit.Visit(declSubclassVisitor); + + var declKindEnum = declClass.FindEnum("Kind"); + declKindEnum.MoveToNamespace(declKindEnum.GetRootNamespace()); + declKindEnum.Name = "DeclarationKind"; + CleanupEnumItems(declKindEnum); + + CleanupDeclClass(declClass); + + var declContextClass = declBaseUnit.FindClass("clang::DeclContext"); + var deductionCandidate = declBaseUnit.FindEnum("clang::DeductionCandidate"); + + CleanupDeclContext(declContextClass); + + var multiVersionKind = declUnit.FindEnum("clang::MultiVersionKind"); + var explicitSpecifier = declCxxUnit.FindClass("clang::ExplicitSpecifier"); + var inheritedConstructor = declCxxUnit.FindClass("clang::InheritedConstructor"); + + var specifiersUnit = ctx.ASTContext.TranslationUnits.Find(unit => unit.FileName == "Specifiers.h"); + var explicitSpecKind = specifiersUnit.FindEnum("clang::ExplicitSpecKind"); + var accessSpecifier = specifiersUnit.FindEnum("clang::AccessSpecifier"); + var storageClass = specifiersUnit.FindEnum("clang::StorageClass"); + var threadStorageClassSpecifier = specifiersUnit.FindEnum("clang::ThreadStorageClassSpecifier"); + var templateSpecializationKind = specifiersUnit.FindEnum("clang::TemplateSpecializationKind"); + var constexprSpecKind = specifiersUnit.FindEnum("clang::ConstexprSpecKind"); + var inClassInitStyle = specifiersUnit.FindEnum("clang::InClassInitStyle"); + + var linkageUnit = ctx.ASTContext.TranslationUnits.Find(unit => unit.FileName == "Linkage.h"); + var linkage = linkageUnit.FindEnum("clang::Linkage"); + var languageLinkage = linkageUnit.FindEnum("clang::LanguageLinkage"); + + var visibilityUnit = ctx.ASTContext.TranslationUnits.Find(unit => unit.FileName == "Visibility.h"); + var visibility = visibilityUnit.FindEnum("clang::Visibility"); + var linkageInfo = visibilityUnit.FindClass("clang::LinkageInfo"); + + var pragmaKindsUnit = ctx.ASTContext.TranslationUnits.Find(unit => unit.FileName == "PragmaKinds.h"); + var pragmaMSCommentKind = pragmaKindsUnit.FindEnum("clang::PragmaMSCommentKind"); + + var exceptionSpecificationTypeUnit = ctx.ASTContext.TranslationUnits.Find(unit => unit.FileName == "ExceptionSpecificationType.h"); + var exceptionSpecificationType = exceptionSpecificationTypeUnit.FindEnum("clang::ExceptionSpecificationType"); + + var builtinsUnit = ctx.ASTContext.TranslationUnits.Find(unit => unit.FileName == "Builtins.h"); + var builtinTemplateKind = builtinsUnit.FindEnum("clang::BuiltinTemplateKind"); + + var redeclarableUnit = ctx.ASTContext.TranslationUnits.Find(unit => unit.FileName.Contains("Redeclarable.h")); + + var redeclarableClass = redeclarableUnit.FindClass("clang::Redeclarable"); + redeclarableClass.TemplateParameters.First().Name = "Decl"; + + var itr = redeclarableClass.FindClass("redecl_iterator"); + itr.Name = "Decl"; + itr.MoveToNamespace(itr.GetRootNamespace()); + itr.ExplicitlyIgnore(); + + var CXXRecordDeclClass = declCxxUnit.FindClass("clang::CXXRecordDecl"); + var friend_itr = CXXRecordDeclClass.FindClass("friend_iterator"); + friend_itr.Name = "FriendDecl"; + friend_itr.MoveToNamespace(friend_itr.GetRootNamespace()); + friend_itr.ExplicitlyIgnore(); + + var mergeableClass = redeclarableUnit.FindClass("clang::Mergeable"); + mergeableClass.TemplateParameters.First().Name = "Decl"; + + var memberSpecializationInfo = declTemplateUnit.FindClass("clang::MemberSpecializationInfo"); + var functionTemplateSpecializationInfo = declTemplateUnit.FindClass("clang::FunctionTemplateSpecializationInfo"); + var dependentFunctionTemplateSpecializationInfo = declTemplateUnit.FindClass("clang::DependentFunctionTemplateSpecializationInfo"); + var templateParmPosition = declTemplateUnit.FindClass("clang::TemplateParmPosition"); + + var templateBaseUnit = ctx.ASTContext.TranslationUnits.Find(unit => unit.FileName.Contains("TemplateBase.h")); + var aSTTemplateArgumentListInfo = templateBaseUnit.FindClass("clang::ASTTemplateArgumentListInfo"); + + // TODO: Move to type + var typeUnit = ctx.ASTContext.TranslationUnits.Find(unit => unit.FileName == "Type.h"); + var refQualifierKind = typeUnit.FindEnum("clang::RefQualifierKind"); + var qualifiers = typeUnit.FindClass("clang::Qualifiers"); + + var decls = new Declaration[] + { + declKindEnum, + multiVersionKind, + explicitSpecKind, + explicitSpecifier, + inheritedConstructor, + accessSpecifier, + storageClass, + threadStorageClassSpecifier, + templateSpecializationKind, + builtinTemplateKind, + inClassInitStyle, + constexprSpecKind, + linkage, + languageLinkage, + visibility, + linkageInfo, + pragmaMSCommentKind, + exceptionSpecificationType, + declContextClass, + redeclarableClass, + mergeableClass, + memberSpecializationInfo, + functionTemplateSpecializationInfo, + dependentFunctionTemplateSpecializationInfo, + aSTTemplateArgumentListInfo, + templateParmPosition, + deductionCandidate, + refQualifierKind, // TODO: Move to type + qualifiers, // TODO: Move to type + } + .Union(declSubclassVisitor.Classes); + + // Validate inheritance for declarations + var validator = new InheritanceValidator(); + validator.ValidateInheritance(decls); + + // Write the native declarations headers + CodeGeneratorHelpers.CppTypePrinter.PushContext(TypePrinterContextKind.Normal); + { + var declsCodeGen = new DeclDeclarationsCodeGenerator(ctx, decls); + declsCodeGen.GenerateDeclarations(); + WriteFile(declsCodeGen, Path.Combine(OutputPath, "CppParser", "Declaration.h")); + } + CodeGeneratorHelpers.CppTypePrinter.PopContext(); + + /*var defsCodeGen = new DeclDefinitionsCodeGenerator(ctx, decls); + defsCodeGen.GenerateDefinitions(); + WriteFile(defsCodeGen, Path.Combine(OutputPath, "CppParser", "Decl.cpp")); + + // Write the native parsing routines + var parserCodeGen = new DeclParserCodeGenerator(ctx, decls); + parserCodeGen.GenerateParser(); + WriteFile(parserCodeGen, Path.Combine(OutputPath, "CppParser", "ParseDecl.cpp")); + + // Write the managed declarations + var managedCodeGen = new ManagedParserCodeGenerator(ctx, decls); + managedCodeGen.GenerateDeclarations(); + WriteFile(managedCodeGen, Path.Combine(OutputPath, "AST", "Decl.cs")); + + managedCodeGen = new DeclASTConverterCodeGenerator(ctx, decls); + managedCodeGen.Process(); + WriteFile(managedCodeGen, Path.Combine(OutputPath, "Parser", "ASTConverter.Decl.cs"));*/ + } + + private void CleanupDeclClass(Class declClass) + { + var decl_itr = declClass.FindClass("redecl_iterator"); + decl_itr.Name = "Decl"; + decl_itr.MoveToNamespace(decl_itr.GetRootNamespace()); + decl_itr.ExplicitlyIgnore(); + + declClass.Properties + .FindAll(x => x.Name + is "langOpts" // Reason: Not needed + or "declKindName" // Reason: Can use Enum.ToString() + or "specific_attrs" // Reason: Handled in C# + or "versionIntroduced" // Reason: Not needed + || x.Name.Contains("module", StringComparison.InvariantCultureIgnoreCase) // TODO: Modules are not supported currently + ) + .ForEach(x => x.ExplicitlyIgnore()); + } + + + private void CleanupDeclContext(Class declContextClass) + { + foreach (Class @class in declContextClass.Classes.ToArray() + .Where(c => c.OriginalName.EndsWith("_iterator"))) + { + // Move to root namespace to prevent qualified names + @class.MoveToNamespace(@class.GetRootNamespace()); + + if (@class.OriginalName.Contains("decl")) + { + @class.Name = "Decl"; + } + else if (@class.OriginalName.Contains("udir")) + { + @class.Name = "UsingDirectiveDecl"; + } + + @class.ExplicitlyIgnore(); + } + + declContextClass.Methods + .FindAll(x => x.Name + is "noload_decls" // Reason: No longer relevant + or "ddiags" // Reason: No longer relevant + or "lookups" // TODO: Difficult to map + ).ForEach(x => x.ExplicitlyIgnore()); + + declContextClass.Properties + .FindAll(x => x.Name + is "declKindName" // Reason: In C# you can use Enum.ToString() + or "decls_empty" // Reason: This is a simple IsEmpty() check + or "lookupPtr" // TODO: Difficult to map + ) + .ForEach(x => x.ExplicitlyIgnore()); + } + private static void CleanupEnumItems(Enumeration exprClassEnum) { foreach (var item in exprClassEnum.Items) @@ -320,7 +588,7 @@ namespace CppSharp { private static void Check(Declaration decl) { - if (string.IsNullOrWhiteSpace(decl.Name)) + if (decl is not TranslationUnit && string.IsNullOrWhiteSpace(decl.Name)) { decl.ExplicitlyIgnore(); return; @@ -345,16 +613,26 @@ namespace CppSharp decl.ExplicitlyIgnore(); } + public override bool VisitDeclaration(Declaration decl) + { + if (!base.VisitDeclaration(decl) || decl.Ignore) + return false; + + Check(decl); + return !decl.Ignore; + } + public override bool VisitClassDecl(Class @class) { - // - // Statements - // + if (@class.Ignore) + return false; - if (CodeGeneratorHelpers.IsAbstractStmt(@class)) + if (IsAbstractType(@class) || IsAbstractDecl(@class) || IsAbstractStmt(@class)) @class.IsAbstract = true; - Check(@class); + // + // Statements + // foreach (var @base in @class.Bases) { @@ -426,32 +704,45 @@ namespace CppSharp } } - return base.VisitClassDecl(@class); + return base.VisitClassDecl(@class) && !@class.Ignore; } public override bool VisitClassTemplateDecl(ClassTemplate template) { - Check(template); return base.VisitClassTemplateDecl(template); } public override bool VisitTypeAliasTemplateDecl(TypeAliasTemplate template) { - Check(template); return base.VisitTypeAliasTemplateDecl(template); } public override bool VisitProperty(Property property) { - if (property.Name == "stripLabelLikeStatements") + if (!base.VisitProperty(property)) + return false; + + // TODO: Remove null check once auto types are handled properly + if (property.Type == null || property.Name == "stripLabelLikeStatements") + { + property.ExplicitlyIgnore(); + return false; + } + + var typeName = property.Type.Visit(CodeGeneratorHelpers.CppTypePrinter).Type; + + // Ignore properties that use internal Clang types + if (typeName.Contains("DeclContext") || + typeName.Contains("ASTContext") || + typeName.Contains("TypeLoc")) property.ExplicitlyIgnore(); - return base.VisitProperty(property); + return true; } public override bool VisitEnumDecl(Enumeration @enum) { - if (AlreadyVisited(@enum)) + if (!base.VisitEnumDecl(@enum)) return false; if (@enum.Name == "APFloatSemantics") @@ -464,7 +755,7 @@ namespace CppSharp RemoveEnumItemsPrefix(@enum); - return base.VisitEnumDecl(@enum); + return true; } private void RemoveEnumItemsPrefix(Enumeration @enum) @@ -586,7 +877,7 @@ namespace CppSharp public override bool VisitClassDecl(Class @class) { - if (!@class.IsGenerated) + if (SkipClass(@class)) return false; GenerateClassSpecifier(@class); @@ -953,6 +1244,7 @@ namespace CppSharp { Context.Options.GeneratorKind = GeneratorKind.CPlusPlus; CTypePrinter.PushScope(TypePrintScopeKind.Local); + CTypePrinter.PushContext(TypePrinterContextKind.Normal); GenerateFilePreamble(CommentKind.BCPL); NewLine(); @@ -1042,7 +1334,12 @@ namespace CppSharp return $"{typeName}()"; if (property.Type.TryGetEnum(out Enumeration @enum)) + { + if (@enum.Items.Count == 0) // Strongly typed integer? + return $"({GetQualifiedName(@enum)})0"; + return $"{GetQualifiedName(@enum)}::{@enum.Items.First().Name}"; + } return "0"; } diff --git a/src/CppParser/Bootstrap/CodeGeneratorHelpers.cs b/src/CppParser/Bootstrap/CodeGeneratorHelpers.cs index 95033ede..6505c9e4 100644 --- a/src/CppParser/Bootstrap/CodeGeneratorHelpers.cs +++ b/src/CppParser/Bootstrap/CodeGeneratorHelpers.cs @@ -9,6 +9,44 @@ using CppSharp.Passes; namespace CppSharp { + class TemplateArgumentHandler + { + public static string GetTemplateArgumentTypeName(TemplateArgument arg, CppTypePrinter printer) + { + switch (arg.Kind) + { + case TemplateArgument.ArgumentKind.Type: + return GetTemplateTypeArgName(arg.Type, printer); + case TemplateArgument.ArgumentKind.Declaration: + return GetTemplateDeclArgName(arg.Declaration, printer); + case TemplateArgument.ArgumentKind.NullPtr: + return "nullptr_t"; + case TemplateArgument.ArgumentKind.Integral: + return GetTemplateIntegralArgName(arg.Integral, printer); + default: + throw new NotImplementedException($"Unhandled template argument kind: {arg.Kind}"); + } + } + + private static string GetTemplateTypeArgName(QualifiedType type, CppTypePrinter printer) + { + var typeStr = type.Type.Visit(printer).Type; + if (type.Type.IsPointer()) + return $"{typeStr}*"; + return typeStr; + } + + private static string GetTemplateDeclArgName(Declaration decl, CppTypePrinter printer) + { + return decl?.Visit(printer).Type ?? "nullptr"; + } + + private static string GetTemplateIntegralArgName(long value, CppTypePrinter printer) + { + return value.ToString(); + } + } + internal static class CodeGeneratorHelpers { internal static CppTypePrinter CppTypePrinter; @@ -31,6 +69,17 @@ namespace CppSharp or "OverloadExpr" or "CoroutineSuspendExpr"; + public static bool SkipClass(Class @class) + { + if (!@class.IsGenerated) + return true; + + if (@class.Access != AccessSpecifier.Public) + return true; + + return false; + } + public static bool SkipProperty(Property property, bool skipBaseCheck = false) { if (!property.IsGenerated) @@ -61,11 +110,22 @@ namespace CppSharp var typeName = property.Type.Visit(CppTypePrinter).Type; + // General properties. + if (typeName.Contains("_iterator") || + typeName.Contains("_range") || + property.Name.Contains("_begin") || + property.Name.Contains("_end") || + property.Name.Contains("_empty") || + property.Name.Contains("_size")) + return true; + + + return false; // // Statement properties. // - if (typeName.Contains("LabelDecl") || + /*if (typeName.Contains("LabelDecl") || typeName.Contains("VarDecl") || typeName.Contains("Token") || typeName.Contains("CapturedDecl") || @@ -77,7 +137,7 @@ namespace CppSharp typeName.Contains("NestedNameSpecifierLoc") || typeName.Contains("DeclarationNameInfo") || typeName.Contains("DeclGroupRef")) - return true; + return true;*/ // // Expressions @@ -209,11 +269,6 @@ namespace CppSharp if (typeName.Contains("StorageDuration")) return true; - // General properties. - if (typeName.Contains("_iterator") || - typeName.Contains("_range")) - return true; - if (typeName.Contains("ArrayRef")) return true; @@ -246,7 +301,7 @@ namespace CppSharp public static bool SkipMethod(Method method) { - if (method.Ignore) + if (method.IsGenerated) return true; var @class = method.Namespace as Class; @@ -335,8 +390,14 @@ namespace CppSharp if (kind == GeneratorKind.CPlusPlus) { - if (Generators.C.CCodeGenerator.IsReservedKeyword(name)) + if (name == "inline") + { + name = "isInline"; + } + else if (Generators.C.CCodeGenerator.IsReservedKeyword(name)) + { name = $"_{name}"; + } } else if (kind == GeneratorKind.CSharp) { @@ -372,7 +433,7 @@ namespace CppSharp TypePrinter typePrinter) { var qualifiedType = new QualifiedType(type); - if (qualifiedType.Type.IsPointerTo(out TagType tagType)) + if (qualifiedType.Type.IsPointerTo(out TagType _)) qualifiedType = qualifiedType.StripConst(); var typeName = qualifiedType.Type.Visit(typePrinter).Type; @@ -423,61 +484,23 @@ namespace CppSharp } } - string className = null; - if (typeName.Contains("FieldDecl")) - className = "Field"; - else if (typeName.Contains("NamedDecl")) - className = "Declaration"; - else if (typeName.Contains("CXXMethodDecl")) - className = "Method"; - else if (typeName.Contains("FunctionDecl")) - className = "Function"; - else if (typeName.Contains("FunctionTemplateDecl")) - className = "FunctionTemplate"; - else if (typeName is "Decl" or "Decl*") - className = "Declaration"; - - if (className != null) - return (typePrinter is CppTypePrinter) ? $"{className}*" : className; - return typeName; } public static AST.Type GetIteratorType(Method method) { - var retType = method.ReturnType.Type; - - TemplateSpecializationType templateSpecType; - TypedefType typedefType; - TypedefNameDecl typedefNameDecl; + var retType = method.ReturnType.Type.Desugar(); - if (retType is TemplateSpecializationType) - { - templateSpecType = retType as TemplateSpecializationType; - typedefType = templateSpecType.Arguments[0].Type.Type as TypedefType; - typedefNameDecl = typedefType.Declaration as TypedefNameDecl; - } - else - { - typedefType = retType as TypedefType; - typedefNameDecl = typedefType.Declaration as TypedefNameDecl; - templateSpecType = typedefNameDecl.Type as TemplateSpecializationType; - typedefType = templateSpecType.Arguments[0].Type.Type as TypedefType; - typedefNameDecl = typedefType.Declaration as TypedefNameDecl; - typedefType = typedefNameDecl.Type as TypedefType; - if (typedefType != null) - typedefNameDecl = typedefType.Declaration as TypedefNameDecl; - } + if (retType is TemplateSpecializationType templateSpecType) + retType = templateSpecType.Arguments[0].Type.Type.Desugar(); - var iteratorType = typedefNameDecl.Type; - if (iteratorType.IsPointerTo(out PointerType pointee)) - iteratorType = iteratorType.GetPointee(); + if (retType.IsPointerTo(out PointerType pointee)) + retType = pointee; - return iteratorType; + return retType; } - public static string GetIteratorTypeName(AST.Type iteratorType, - TypePrinter typePrinter) + public static string GetIteratorTypeName(AST.Type iteratorType, TypePrinter typePrinter) { if (iteratorType.IsPointer()) iteratorType = iteratorType.GetFinalPointee(); @@ -494,7 +517,8 @@ namespace CppSharp else if (iteratorTypeName.Contains("StmtIterator")) iteratorTypeName = "Stmt"; - else if (iteratorTypeName.Contains("CastIterator")) + else if (iteratorTypeName.Contains("CastIterator") || + iteratorTypeName.Contains("DeclContext::")) { if (iteratorType is TypedefType typedefType) iteratorType = typedefType.Declaration.Type; @@ -509,9 +533,6 @@ namespace CppSharp iteratorTypeName = CleanClangNamespaceFromName(iteratorTypeName); } - if (iteratorTypeName == "Decl") - iteratorTypeName = "Declaration"; - if (typePrinter is CppTypePrinter) return $"{iteratorTypeName}*"; @@ -547,5 +568,109 @@ namespace CppSharp a[0] = char.ToUpper(a[0]); return new string(a); } + + public static bool SkipDeclProperty(Property property) + { + if (!property.IsGenerated || property.Access != AccessSpecifier.Public) + return true; + + var @class = property.Namespace as Class; + + if (@class.GetBaseProperty(property) != null) + return true; + + var typeName = property.Type.Visit(CppTypePrinter).Type; + + // Skip properties that deal with source locations/ranges + if (typeName.Contains("SourceLocation") || typeName.Contains("SourceRange")) + return true; + + // Skip Clang-specific internal properties + if (typeName.Contains("ASTContext") || typeName.Contains("DeclContext")) + return true; + + // Skip template-specific properties that are handled separately + if (typeName.Contains("TemplateParameterList") || + typeName.Contains("TemplateArgument")) + return true; + + return false; + } + + public static bool SkipTypeProperty(Property property) + { + if (!property.IsGenerated || property.Access != AccessSpecifier.Public) + return true; + + var @class = property.Namespace as Class; + + if (@class.GetBaseProperty(property) != null) + return true; + + var typeName = property.Type.Visit(CppTypePrinter).Type; + + // Skip source location properties + if (typeName.Contains("SourceLocation")) + return true; + + // Skip internal Clang type properties + if (typeName.Contains("TypeLoc") || typeName.Contains("ASTContext")) + return true; + + return false; + } + + public static bool IsAbstractType(Class @class) => + @class.Name is "Type" + or "ArrayType" + or "TagType" + or "FunctionType"; + + public static bool IsAbstractDecl(Class @class) => + @class.Name is "Decl" + or "NamedDecl" + or "ValueDecl" + or "TypeDecl" + or "DeclContext"; + + public static string GetPropertyAccessorName(Property property, bool isGetter) + { + var baseName = FirstLetterToUpperCase(GetDeclName(property)); + return isGetter ? $"Get{baseName}" : $"Set{baseName}"; + } + + public static string GetPropertyTypeName(Property property, bool includeNamespace = true) + { + var typeName = GetDeclTypeName(property); + + // Handle special cases + if (typeName.Contains("QualType") || + (property.Type.IsPointerTo(out TagType tagType) && + tagType.Declaration?.Name.Contains("Type") == true)) + { + return includeNamespace ? $"AST::{typeName}" : typeName; + } + + // Handle template types + if (property.Type is TemplateSpecializationType templateType) + { + var templateName = templateType.Template.TemplatedDecl.Name; + return includeNamespace ? $"AST::{templateName}" : templateName; + } + + return typeName; + } + + public static bool IsTypeProperty(Property property) + { + if (property.Type.IsPointerTo(out TagType tagType)) + return tagType.Declaration?.Name.Contains("Type") == true; + + var typeName = GetDeclTypeName(property); + return typeName.Contains("QualType") || + typeName.Contains("Type") || + (property.Type is TemplateSpecializationType templateType && + templateType.Template.TemplatedDecl.Name.Contains("Type")); + } } } \ No newline at end of file diff --git a/src/CppParser/Bootstrap/DeclCodeGenerators.cs b/src/CppParser/Bootstrap/DeclCodeGenerators.cs new file mode 100644 index 00000000..ead8b855 --- /dev/null +++ b/src/CppParser/Bootstrap/DeclCodeGenerators.cs @@ -0,0 +1,221 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CppSharp.AST; +using CppSharp.AST.Extensions; +using CppSharp.Generators; +using CppSharp.Generators.C; +using CppSharp.Generators.CSharp; + +using static CppSharp.CodeGeneratorHelpers; + +namespace CppSharp +{ + internal class DeclDeclarationsCodeGenerator : DeclarationsCodeGenerator + { + public DeclDeclarationsCodeGenerator(BindingContext context, IEnumerable declarations) + : base(context, declarations) + { + } + + public override string BaseTypeName => "Decl"; + + public override void GenerateIncludes() + { + WriteInclude("Sources.h", CInclude.IncludeKind.Quoted); + WriteInclude("Types.h", CInclude.IncludeKind.Quoted); + WriteInclude("string", CInclude.IncludeKind.Angled); + } + + public override void GenerateForwardDecls() + { + WriteLine("class Expr;"); + WriteLine("class Stmt;"); + WriteLine("class LabelStmt;"); + WriteLine("class EvaluatedStmt;"); + WriteLine("class CompoundStmt;"); + WriteLine("enum class OverloadedOperatorKind;"); + NewLine(); + WriteLine("class Declaration;"); + WriteLine("class UsingDirectiveDecl;"); + WriteLine("class FriendDecl;"); + WriteLine("class ConstructorUsingShadowDecl;"); + WriteLine("class LinkageSpecDecl;"); + WriteLine("class NamedDecl;"); + WriteLine("class NamespaceDecl;"); + WriteLine("class TemplateDecl;"); + WriteLine("class ClassTemplateDecl;"); + WriteLine("class VarTemplateDecl;"); + WriteLine("class TypeAliasTemplateDecl;"); + WriteLine("class FunctionDecl;"); + WriteLine("class FunctionTemplateDecl;"); + WriteLine("class CXXMethodDecl;"); + WriteLine("class CXXConstructorDecl;"); + WriteLine("class CXXDestructorDecl;"); + WriteLine("class BaseUsingDecl;"); + } + + public override bool VisitClassDecl(Class @class) + { + if (SkipClass(@class)) + return false; + + @class.Bases.Find(x => x.Class?.Name == "Node") + ?.ExplicitlyIgnore(); + + return base.VisitClassDecl(@class); + } + + public override bool GenerateClassBody(Class @class) + { + Unindent(); + WriteLine("public:"); + Indent(); + + PushBlock(); + VisitDeclContext(@class); + PopBlock(NewLineKind.Always); + + WriteLine($"{@class.Name}();"); + + foreach (var method in @class.Methods) + { + if (SkipMethod(method)) + continue; + + var iteratorType = GetIteratorType(method); + string iteratorTypeName = GetIteratorTypeName(iteratorType, CodeGeneratorHelpers.CppTypePrinter); + + WriteLine($"VECTOR({iteratorTypeName}, {method.Name})"); + } + + foreach (var property in @class.Properties) + { + if (SkipProperty(property) || property.IsStatic) + continue; + + string typeName = GetDeclTypeName(property); + + if (typeName.StartsWith("TemplateArgumentList")) + { + WriteLine($"VECTOR(TemplateArgument*, {GetDeclName(property)})"); + } + else if (typeName.StartsWith("TemplateParameterList")) + { + WriteLine($"VECTOR(NamedDecl*, {GetDeclName(property)})"); + } + else + { + WriteLine($"{typeName} {GetDeclName(property)};"); + } + } + + return true; + } + } + + internal class DeclDefinitionsCodeGenerator : DefinitionsCodeGenerator + { + public DeclDefinitionsCodeGenerator(BindingContext context, IEnumerable declarations) + : base(context, declarations) + { + } + + public override string BaseTypeName => "Decl"; + + public override void GenerateIncludes() + { + GenerateCommonIncludes(); + NewLine(); + WriteInclude("Decl.h", CInclude.IncludeKind.Quoted); + WriteInclude("Types.h", CInclude.IncludeKind.Quoted); + } + + public override bool VisitClassDecl(Class @class) + { + if (!@class.IsGenerated) + return false; + + VisitDeclContext(@class); + + var isBaseType = @class.Name == BaseTypeName; + if (!isBaseType && !@class.HasBaseClass) + { + WriteLine($"{GetQualifiedName(@class)}::{@class.Name}()"); + WriteOpenBraceAndIndent(); + UnindentAndWriteCloseBrace(); + NewLine(); + return true; + } + + WriteLine($"{@class.Name}::{@class.Name}()"); + GenerateMemberInits(@class); + WriteOpenBraceAndIndent(); + UnindentAndWriteCloseBrace(); + NewLine(); + + foreach (var method in @class.Methods) + { + if (SkipMethod(method)) + continue; + + var iteratorType = GetIteratorType(method); + string iteratorTypeName = GetIteratorTypeName(iteratorType, + CodeGeneratorHelpers.CppTypePrinter); + + WriteLine($"DEF_VECTOR({@class.Name}, {iteratorTypeName}, {method.Name})"); + NewLine(); + } + + return true; + } + } + + internal class DeclASTConverterCodeGenerator : ASTConverterCodeGenerator + { + public DeclASTConverterCodeGenerator(BindingContext context, IEnumerable declarations) + : base(context, declarations) + { + } + + public override string BaseTypeName => "Decl"; + + public override bool IsAbstractASTNode(Class kind) + { + return IsAbstractDecl(kind); + } + + protected override void GenerateVisitorSwitch(IEnumerable classes) + { + WriteLine($"switch({ParamName}.DeclKind)"); + WriteOpenBraceAndIndent(); + + GenerateSwitchCases(classes); + + UnindentAndWriteCloseBrace(); + } + + private void GenerateSwitchCases(IEnumerable classes) + { + foreach (var className in classes) + { + WriteLine($"case Parser.AST.{BaseTypeName}Kind.{className}:"); + WriteLineIndent($"return Visit{className}({ParamName} as Parser.AST.{className}Decl);"); + } + foreach (var className in classes) + { + WriteLine($"case StmtClass.{className}:"); + WriteOpenBraceAndIndent(); + + WriteLine($"var _{ParamName} = {className}.__CreateInstance({ParamName}.__Instance);"); + + WriteLine($"return Visit{className}(_{ParamName});"); + + UnindentAndWriteCloseBrace(); + } + + WriteLine("default:"); + WriteLineIndent($"throw new System.NotImplementedException({ParamName}.DeclKind.ToString());"); + } + } +} \ No newline at end of file diff --git a/src/CppParser/Bootstrap/InheritanceValidator.cs b/src/CppParser/Bootstrap/InheritanceValidator.cs new file mode 100644 index 00000000..920b9aff --- /dev/null +++ b/src/CppParser/Bootstrap/InheritanceValidator.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CppSharp.AST; + +namespace CppSharp +{ + class InheritanceValidator + { + private readonly HashSet _processedClasses = new(); + + public void ValidateInheritance(IEnumerable declarations) + { + foreach (var decl in declarations.OfType()) + { + if (!_processedClasses.Add(decl.Name)) + continue; + + ValidateClassInheritance(decl); + } + } + + private static void ValidateClassInheritance(Class @class) + { + if (@class.Bases.Count == 0) + return; + + foreach (var @base in @class.Bases) + { + if (@base.Class == null) + continue; + + ValidateClassInheritance(@base.Class); + } + + // Ensure base class properties don't conflict + foreach (var property in @class.Properties) + { + if (@class.GetBaseProperty(property) != null) + { + property.ExplicitlyIgnore(); + } + } + + // Handle method overrides + foreach (var method in @class.Methods) + { + if (@class.GetBaseMethod(method) != null) + { + method.ExplicitlyIgnore(); + } + } + } + } +} \ No newline at end of file diff --git a/src/CppParser/Bootstrap/ParserCodeGenerators.cs b/src/CppParser/Bootstrap/ParserCodeGenerators.cs new file mode 100644 index 00000000..acc7b922 --- /dev/null +++ b/src/CppParser/Bootstrap/ParserCodeGenerators.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CppSharp.AST; +using CppSharp.AST.Extensions; +using CppSharp.Generators; +using CppSharp.Generators.C; +using CppSharp.Generators.CSharp; + +using static CppSharp.CodeGeneratorHelpers; + +namespace CppSharp +{ + class DeclParserCodeGenerator : StmtParserCodeGenerator + { + public DeclParserCodeGenerator(BindingContext context, + IEnumerable declarations) + : base(context, declarations, null) + { + } + + public override void GenerateIncludes() + { + WriteInclude("clang/AST/Decl.h", CInclude.IncludeKind.Angled); + WriteInclude("clang/AST/DeclCXX.h", CInclude.IncludeKind.Angled); + WriteInclude("clang/AST/DeclTemplate.h", CInclude.IncludeKind.Angled); + } + + public override string BaseTypeName => "Decl"; + + public override string MethodSig => + "AST::Decl* Parser::WalkDeclaration(const clang::Decl* Decl)"; + + public override bool VisitProperty(Property property) + { + if (SkipDeclProperty(property)) + return false; + + var typeName = GetDeclTypeName(property); + var fieldName = GetDeclName(property); + var methodName = property.GetMethod?.Name; + + Write($"_D->{fieldName} = "); + if (property.Type.TryGetClass(out Class @class)) + { + if (@class.Name.Contains("Type")) + WriteLine($"GetQualifiedType(D->{methodName}());"); + else if (@class.Name.Contains("Decl")) + WriteLine($"WalkDeclaration(D->{methodName}());"); + else + WriteLine($"D->{methodName}();"); + } + else + WriteLine($"D->{methodName}();"); + + return true; + } + } + + class TypeParserCodeGenerator : StmtParserCodeGenerator + { + public TypeParserCodeGenerator(BindingContext context, + IEnumerable declarations) + : base(context, declarations, null) + { + } + + public override void GenerateIncludes() + { + WriteInclude("clang/AST/Type.h", CInclude.IncludeKind.Angled); + WriteInclude("clang/AST/CXXType.h", CInclude.IncludeKind.Angled); + } + + public override string BaseTypeName => "Type"; + + public override string MethodSig => + "AST::Type* Parser::WalkType(const clang::Type* Type)"; + + public override bool VisitProperty(Property property) + { + if (CodeGeneratorHelpers.SkipTypeProperty(property)) + return false; + + var typeName = GetDeclTypeName(property); + var fieldName = GetDeclName(property); + var methodName = property.GetMethod?.Name; + + WriteLine($"_T->{fieldName} = "); + if (property.Type.TryGetClass(out Class @class)) + { + if (@class.Name.Contains("Type")) + WriteLine($"GetQualifiedType(T->{methodName}());"); + else if (@class.Name.Contains("Decl")) + WriteLine($"WalkDeclaration(T->{methodName}());"); + else + WriteLine($"T->{methodName}();"); + } + else + WriteLine($"T->{methodName}();"); + + return true; + } + } +} \ No newline at end of file diff --git a/src/CppParser/Bootstrap/Properties/launchSettings.json b/src/CppParser/Bootstrap/Properties/launchSettings.json index a689a483..9b11eed0 100644 --- a/src/CppParser/Bootstrap/Properties/launchSettings.json +++ b/src/CppParser/Bootstrap/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "CppSharp.Parser.Bootstrap": { "commandName": "Project", - "nativeDebugging": true + "nativeDebugging": false } } } \ No newline at end of file diff --git a/src/CppParser/Bootstrap/StmtCodeGenerators.cs b/src/CppParser/Bootstrap/StmtCodeGenerators.cs index 77ed94f1..1d50a918 100644 --- a/src/CppParser/Bootstrap/StmtCodeGenerators.cs +++ b/src/CppParser/Bootstrap/StmtCodeGenerators.cs @@ -66,8 +66,7 @@ namespace CppSharp continue; var iteratorType = GetIteratorType(method); - string iteratorTypeName = GetIteratorTypeName(iteratorType, - CodeGeneratorHelpers.CppTypePrinter); + string iteratorTypeName = GetIteratorTypeName(iteratorType, CodeGeneratorHelpers.CppTypePrinter); WriteLine($"VECTOR({iteratorTypeName}, {method.Name})"); } @@ -114,6 +113,12 @@ namespace CppSharp return true; } + //PushBlock(BlockKind.Class, @class); + + //GenerateDeclarationCommon(@class); + + //GenerateClassSpecifier(@class); + WriteLine($"{@class.Name}::{@class.Name}()"); var stmtMember = isStmt ? "stmtClass" : @class.BaseClass.Name; var stmtClass = IsAbstractStmt(@class) ? "NoStmt" : @class.Name; @@ -301,9 +306,22 @@ namespace CppSharp { walkMethod = "WalkStatement"; } + else if (iteratorTypeName.Contains("Attr")) + { + walkMethod = "WalkDeclaration"; + } + else if (iteratorTypeName.Contains("CXXBaseSpecifier")) + { + walkMethod = "WalkDeclaration"; + } + else if (iteratorTypeName.Contains("CXXCtorInitializer")) + { + walkMethod = "WalkDeclaration"; + } else { - throw new NotImplementedException(); + //throw new NotImplementedException(); + walkMethod = "WalkDeclaration"; } WriteLine("auto _ES = {0}{1}(_E);", isBaseType ? string.Empty : $"(AST::{iteratorTypeName})", walkMethod); diff --git a/src/CppParser/Bootstrap/TypeCodeGenerators.cs b/src/CppParser/Bootstrap/TypeCodeGenerators.cs new file mode 100644 index 00000000..7961b59d --- /dev/null +++ b/src/CppParser/Bootstrap/TypeCodeGenerators.cs @@ -0,0 +1,323 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CppSharp.AST; +using CppSharp.AST.Extensions; +using CppSharp.Generators; +using CppSharp.Generators.C; +using CppSharp.Generators.CSharp; + +using static CppSharp.CodeGeneratorHelpers; + +namespace CppSharp +{ + class TypeDeclarationsCodeGenerator : StmtDeclarationsCodeGenerator + { + public TypeDeclarationsCodeGenerator(BindingContext context, + IEnumerable declarations) + : base(context, declarations) + { + } + + public override void GenerateIncludes() + { + WriteInclude("Sources.h", CInclude.IncludeKind.Quoted); + WriteInclude("string", CInclude.IncludeKind.Angled); + WriteInclude("memory", CInclude.IncludeKind.Angled); + WriteInclude("vector", CInclude.IncludeKind.Angled); + } + + public override void GenerateForwardDecls() + { + WriteLine("class Decl;"); + WriteLine("class TemplateArgument;"); + WriteLine("class TemplateParameterList;"); + } + + public override bool VisitClassDecl(Class @class) + { + if (!@class.IsGenerated) + return false; + + GenerateClassSpecifier(@class); + NewLine(); + + WriteOpenBraceAndIndent(); + + PushBlock(); + VisitDeclContext(@class); + PopBlock(NewLineKind.Always); + + WriteLine($"public:"); + Indent(); + + WriteLine($"{@class.Name}();"); + + if (@class.Name == "Type") + WriteLine("TypeClass typeClass;"); + + foreach (var method in @class.Methods) + { + if (SkipMethod(method)) + continue; + + GenerateMethod(method); + } + + foreach (var property in @class.Properties) + { + if (SkipProperty(property)) + continue; + + GenerateProperty(property); + } + + Unindent(); + UnindentAndWriteCloseBrace(); + + return true; + } + + protected void GenerateMethod(Method method) + { + // Validate all method parameters first + foreach (var param in method.Parameters) + { + ValidateTypeMethodParameter(param); + } + + var iteratorType = GetIteratorType(method); + var iteratorTypeName = GetIteratorTypeName(iteratorType, CodeGeneratorHelpers.CppTypePrinter); + + // Handle special cases for type-specific methods + if (method.ReturnType.Type.IsPointer()) + { + var returnTypeName = ValidateTypeMethodReturnType(method.ReturnType.Type); + WriteLine($"{returnTypeName} Get{method.Name}(uint i);"); + } + else + WriteLine($"{iteratorTypeName} Get{method.Name}(uint i);"); + + WriteLine($"uint Get{method.Name}Count();"); + } + + private string ValidateTypeMethodReturnType(AST.Type type) + { + if (type.IsPointerTo(out TagType tagType)) + { + var pointeeType = tagType.Declaration?.Visit(CodeGeneratorHelpers.CppTypePrinter).Type ?? "void"; + if (pointeeType.Contains("Type") || pointeeType.Contains("QualType")) + return $"AST::{pointeeType}*"; + return $"{pointeeType}*"; + } + + if (type is TemplateSpecializationType template) + { + if (template.Template.TemplatedDecl.Name.Contains("Type")) + return $"AST::{template.Template.TemplatedDecl.Name}"; + } + + return type.Visit(CodeGeneratorHelpers.CppTypePrinter).ToString(); + } + + private void ValidateTypeMethodParameter(Parameter param) + { + // Handle pointer types + if (param.Type.IsPointer()) + { + var pointee = param.Type.GetFinalPointee(); + if (pointee is ArrayType) + { + param.ExplicitlyIgnore(); + return; + } + + // Special handling for type-related pointers + if (pointee is TagType tagType && + tagType.Declaration?.Name.Contains("Type") == true) + { + // These are valid, don't ignore + return; + } + } + + // Handle template parameters specific to types + if (param.Type is TemplateSpecializationType template) + { + var templateName = template.Template.TemplatedDecl.Name; + if (!templateName.Contains("Type") && + !templateName.Contains("QualType")) + { + param.ExplicitlyIgnore(); + } + } + } + + protected void GenerateProperty(Property property) + { + var typeName = GetDeclTypeName(property); + var fieldName = GetDeclName(property); + + // Handle special type properties + if (typeName.Contains("QualType")) + { + WriteLine($"AST::{typeName} {fieldName};"); + + if (property.GetMethod != null) + WriteLine($"AST::{typeName} Get{FirstLetterToUpperCase(fieldName)}() const;"); + if (property.SetMethod != null) + WriteLine($"void Set{FirstLetterToUpperCase(fieldName)}(AST::{typeName} value);"); + } + else if (property.Type.IsPointerTo(out TagType tagType)) + { + var pointeeType = tagType.Declaration?.Visit(CodeGeneratorHelpers.CppTypePrinter).Type ?? typeName; + if (pointeeType.Contains("Type") || pointeeType.Contains("QualType")) + { + WriteLine($"AST::{pointeeType}* {fieldName};"); + + if (property.GetMethod != null) + WriteLine($"AST::{pointeeType}* Get{FirstLetterToUpperCase(fieldName)}() const;"); + if (property.SetMethod != null) + WriteLine($"void Set{FirstLetterToUpperCase(fieldName)}(AST::{pointeeType}* value);"); + } + else + { + WriteLine($"{pointeeType}* {fieldName};"); + + if (property.GetMethod != null) + WriteLine($"{pointeeType}* Get{FirstLetterToUpperCase(fieldName)}() const;"); + if (property.SetMethod != null) + WriteLine($"void Set{FirstLetterToUpperCase(fieldName)}({pointeeType}* value);"); + } + } + // Handle template specialization types + else if (property.Type is TemplateSpecializationType templateType) + { + var templateName = templateType.Template.TemplatedDecl.Name; + WriteLine($"AST::{templateName} {fieldName};"); + + if (property.GetMethod != null) + WriteLine($"AST::{templateName} Get{FirstLetterToUpperCase(fieldName)}() const;"); + if (property.SetMethod != null) + WriteLine($"void Set{FirstLetterToUpperCase(fieldName)}(AST::{templateName} value);"); + } + else + { + WriteLine($"{typeName} {fieldName};"); + + if (property.GetMethod != null) + WriteLine($"{typeName} Get{FirstLetterToUpperCase(fieldName)}() const;"); + if (property.SetMethod != null) + WriteLine($"void Set{FirstLetterToUpperCase(fieldName)}({typeName} value);"); + } + } + } + + class TypeDefinitionsCodeGenerator : StmtDefinitionsCodeGenerator + { + public TypeDefinitionsCodeGenerator(BindingContext context, + IEnumerable declarations) + : base(context, declarations) + { + } + + public override void GenerateIncludes() + { + GenerateCommonIncludes(); + WriteInclude("Type.h", CInclude.IncludeKind.Quoted); + } + + protected void GenerateMethodDefinition(Class @class, Method method) + { + var iteratorType = GetIteratorType(method); + var iteratorTypeName = GetIteratorTypeName(iteratorType, CodeGeneratorHelpers.CppTypePrinter); + + WriteLine($"uint {GetQualifiedName(@class)}::Get{method.Name}Count()"); + WriteOpenBraceAndIndent(); + WriteLine($"return {method.Name}().size();"); + UnindentAndWriteCloseBrace(); + NewLine(); + + // Handle pointer types specially + if (method.ReturnType.Type.IsPointerTo(out TagType tagType)) + { + var pointeeType = tagType.Declaration?.Name ?? iteratorTypeName; + WriteLine($"AST::{pointeeType}* {GetQualifiedName(@class)}::Get{method.Name}(uint i)"); + } + else + WriteLine($"{iteratorTypeName} {GetQualifiedName(@class)}::Get{method.Name}(uint i)"); + + WriteOpenBraceAndIndent(); + WriteLine($"auto elements = {method.Name}();"); + WriteLine($"auto it = elements.begin();"); + WriteLine($"std::advance(it, i);"); + WriteLine($"return *it;"); + UnindentAndWriteCloseBrace(); + NewLine(); + } + + public override bool VisitClassDecl(Class @class) + { + if (!@class.IsGenerated) + return false; + + WriteLine($"{@class.Name}::{@class.Name}()"); + var isBaseType = @class.Name == "Type"; + var typeMember = isBaseType ? "typeClass" : @class.BaseClass.Name; + var typeClass = @class.Name == "Type" ? "None" : @class.Name; + WriteLineIndent($": {typeMember}(TypeClass::{typeClass})"); + GenerateMemberInits(@class); + WriteOpenBraceAndIndent(); + UnindentAndWriteCloseBrace(); + NewLine(); + + foreach (var method in @class.Methods) + { + if (SkipMethod(method)) + continue; + + GenerateMethodDefinition(@class, method); + } + + return true; + } + } + + class TypeASTConverterCodeGenerator : ASTConverterCodeGenerator + { + public TypeASTConverterCodeGenerator(BindingContext context, IEnumerable declarations) + : base(context, declarations) + { + } + + public override string BaseTypeName => "Type"; + + public override bool IsAbstractASTNode(Class kind) + { + return IsAbstractType(kind); + } + + protected override void GenerateVisitorSwitch(IEnumerable classes) + { + WriteLine($"switch({ParamName}.DeclKind)"); + WriteOpenBraceAndIndent(); + + GenerateSwitchCases(classes); + + UnindentAndWriteCloseBrace(); + } + + public void GenerateSwitchCases(IEnumerable classes) + { + foreach (var className in classes) + { + WriteLine($"case Parser.AST.TypeClass.{className}:"); + WriteLineIndent($"return Visit{className}({ParamName} as Parser.AST.{className}Type);"); + } + + WriteLine("default:"); + WriteLineIndent($"throw new System.NotImplementedException(" + + $"{ParamName}.TypeClass.ToString());"); + } + } +} \ No newline at end of file diff --git a/src/CppParser/Decl.h b/src/CppParser/Decl.h index b931e88e..f66deb35 100644 --- a/src/CppParser/Decl.h +++ b/src/CppParser/Decl.h @@ -566,15 +566,6 @@ namespace AST { VECTOR(LayoutBase, Bases) }; - enum class TagKind - { - Struct, - Interface, - Union, - Class, - Enum - }; - class CS_API Class : public DeclarationContext { public: diff --git a/src/CppParser/Types.h b/src/CppParser/Types.h index e8a05f32..70184e2b 100644 --- a/src/CppParser/Types.h +++ b/src/CppParser/Types.h @@ -10,6 +10,7 @@ #include "Helpers.h" namespace CppSharp { namespace CppParser { namespace AST { + class Expr; enum class TypeKind { @@ -34,6 +35,15 @@ namespace CppSharp { namespace CppParser { namespace AST { Vector }; + enum class TagKind + { + Struct, + Interface, + Union, + Class, + Enum + }; + #define DECLARE_TYPE_KIND(kind) \ kind##Type(); @@ -88,6 +98,17 @@ namespace CppSharp { namespace CppParser { namespace AST { long elementSize; }; + class CS_API VariableArrayType : public ArrayType + { + public: + VariableArrayType() + { + sizeType = ArraySize::Variable; + } + + Expr* sizeExpr = nullptr; + }; + class Parameter; enum class CallingConvention diff --git a/src/Generator/Generators/CodeGenerator.cs b/src/Generator/Generators/CodeGenerator.cs index 793b9873..a39263e5 100644 --- a/src/Generator/Generators/CodeGenerator.cs +++ b/src/Generator/Generators/CodeGenerator.cs @@ -427,7 +427,7 @@ namespace CppSharp.Generators public virtual bool VisitClassTemplateDecl(ClassTemplate template) { - throw new NotImplementedException(); + return true; } public virtual bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization) @@ -437,7 +437,7 @@ namespace CppSharp.Generators public virtual bool VisitFunctionTemplateDecl(FunctionTemplate template) { - throw new NotImplementedException(); + return true; } public virtual bool VisitFunctionTemplateSpecializationDecl(FunctionTemplateSpecialization specialization)