Browse Source

Temp

pull/1918/head
duckdoom5 4 months ago
parent
commit
210e79c903
  1. 10
      src/AST/Class.cs
  2. 16
      src/AST/Declaration.cs
  3. 1
      src/CppParser/AST.cpp
  4. 347
      src/CppParser/Bootstrap/Bootstrap.cs
  5. 243
      src/CppParser/Bootstrap/CodeGeneratorHelpers.cs
  6. 221
      src/CppParser/Bootstrap/DeclCodeGenerators.cs
  7. 55
      src/CppParser/Bootstrap/InheritanceValidator.cs
  8. 104
      src/CppParser/Bootstrap/ParserCodeGenerators.cs
  9. 2
      src/CppParser/Bootstrap/Properties/launchSettings.json
  10. 24
      src/CppParser/Bootstrap/StmtCodeGenerators.cs
  11. 323
      src/CppParser/Bootstrap/TypeCodeGenerators.cs
  12. 9
      src/CppParser/Decl.h
  13. 21
      src/CppParser/Types.h
  14. 4
      src/Generator/Generators/CodeGenerator.cs

10
src/AST/Class.cs

@ -274,6 +274,16 @@ namespace CppSharp.AST
return Variables.FirstOrDefault(m => m.Name == name); 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<T>(IDeclVisitor<T> visitor) public override T Visit<T>(IDeclVisitor<T> visitor)
{ {
return visitor.VisitClassDecl(this); return visitor.VisitClassDecl(this);

16
src/AST/Declaration.cs

@ -223,6 +223,22 @@ namespace CppSharp.AST
return namespaces; 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 public string QualifiedName
{ {
get get

1
src/CppParser/AST.cpp

@ -1153,7 +1153,6 @@ namespace CppSharp { namespace CppParser { namespace AST {
kind = DeclarationKind::TranslationUnit; kind = DeclarationKind::TranslationUnit;
} }
TranslationUnit::~TranslationUnit() {}
DEF_VECTOR(TranslationUnit, MacroDefinition*, Macros) DEF_VECTOR(TranslationUnit, MacroDefinition*, Macros)
NativeLibrary::NativeLibrary() NativeLibrary::NativeLibrary()

347
src/CppParser/Bootstrap/Bootstrap.cs

@ -19,7 +19,7 @@ namespace CppSharp
/// </summary> /// </summary>
internal class Bootstrap : ILibrary internal class Bootstrap : ILibrary
{ {
private static bool CreatePatch = true; private static bool CreatePatch = false;
private static string OutputPath = CreatePatch ? "BootstrapPatch" : ""; private static string OutputPath = CreatePatch ? "BootstrapPatch" : "";
private static string GetSourceDirectory(string dir) private static string GetSourceDirectory(string dir)
@ -55,6 +55,7 @@ namespace CppSharp
{ {
driver.Options.GeneratorKind = GeneratorKind.CSharp; driver.Options.GeneratorKind = GeneratorKind.CSharp;
driver.Options.DryRun = true; driver.Options.DryRun = true;
driver.ParserOptions.Verbose = true;
driver.ParserOptions.EnableRTTI = true; driver.ParserOptions.EnableRTTI = true;
driver.ParserOptions.LanguageVersion = LanguageVersion.CPP17_GNU; driver.ParserOptions.LanguageVersion = LanguageVersion.CPP17_GNU;
driver.ParserOptions.SkipLayoutInfo = true; driver.ParserOptions.SkipLayoutInfo = true;
@ -80,10 +81,16 @@ namespace CppSharp
module.Headers.AddRange(new[] module.Headers.AddRange(new[]
{ {
"clang/AST/Stmt.h", //"clang/AST/Stmt.h",
"clang/AST/StmtCXX.h", //"clang/AST/StmtCXX.h",
"clang/AST/Expr.h", //"clang/AST/Expr.h",
"clang/AST/ExprCXX.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")); module.LibraryDirs.Add(Path.Combine(llvmPath, "lib"));
@ -95,12 +102,18 @@ namespace CppSharp
public void Preprocess(Driver driver, ASTContext ctx) public void Preprocess(Driver driver, ASTContext ctx)
{ {
CodeGeneratorHelpers.CppTypePrinter = new CppTypePrinter(driver.Context);
CodeGeneratorHelpers.CppTypePrinter.PushScope(TypePrintScopeKind.Local);
new IgnoreMethodsWithParametersPass { Context = driver.Context } new IgnoreMethodsWithParametersPass { Context = driver.Context }
.VisitASTContext(ctx); .VisitASTContext(ctx);
new GetterSetterToPropertyPass { Context = driver.Context } new GetterSetterToPropertyPass { Context = driver.Context }
.VisitASTContext(ctx); .VisitASTContext(ctx);
new CheckEnumsPass { Context = driver.Context } new CheckEnumsPass { Context = driver.Context }
.VisitASTContext(ctx); .VisitASTContext(ctx);
new CleanCommentsPass { Context = driver.Context }
.VisitASTContext(ctx);
var preprocessDecls = new PreprocessDeclarations(); var preprocessDecls = new PreprocessDeclarations();
foreach (var unit in ctx.TranslationUnits) foreach (var unit in ctx.TranslationUnits)
@ -114,14 +127,13 @@ namespace CppSharp
var exprClass = exprUnit.FindNamespace("clang").FindClass("Expr"); var exprClass = exprUnit.FindNamespace("clang").FindClass("Expr");
var exprSubclassVisitor = new SubclassVisitor(exprClass); var exprSubclassVisitor = new SubclassVisitor(exprClass);
exprUnit.Visit(exprSubclassVisitor); exprUnit.Visit(exprSubclassVisitor);
exprCxxUnit.Visit(exprSubclassVisitor); //exprCxxUnit.Visit(exprSubclassVisitor);
ExprClasses = exprSubclassVisitor.Classes; ExprClasses = exprSubclassVisitor.Classes;
CodeGeneratorHelpers.CppTypePrinter = new CppTypePrinter(driver.Context); GenerateDecl(driver.Context);
CodeGeneratorHelpers.CppTypePrinter.PushScope(TypePrintScopeKind.Local); //GenerateType(driver.Context);
//GenerateStmt(driver.Context);
GenerateStmt(driver.Context); //GenerateExpr(driver.Context);
GenerateExpr(driver.Context);
} }
public void Postprocess(Driver driver, ASTContext ctx) public void Postprocess(Driver driver, ASTContext ctx)
@ -251,6 +263,262 @@ namespace CppSharp
WriteFile(managedCodeGen, Path.Combine(OutputPath, "Parser", "ASTConverter.Stmt.cs")); 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) private static void CleanupEnumItems(Enumeration exprClassEnum)
{ {
foreach (var item in exprClassEnum.Items) foreach (var item in exprClassEnum.Items)
@ -320,7 +588,7 @@ namespace CppSharp
{ {
private static void Check(Declaration decl) private static void Check(Declaration decl)
{ {
if (string.IsNullOrWhiteSpace(decl.Name)) if (decl is not TranslationUnit && string.IsNullOrWhiteSpace(decl.Name))
{ {
decl.ExplicitlyIgnore(); decl.ExplicitlyIgnore();
return; return;
@ -345,16 +613,26 @@ namespace CppSharp
decl.ExplicitlyIgnore(); 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) public override bool VisitClassDecl(Class @class)
{ {
// if (@class.Ignore)
// Statements return false;
//
if (CodeGeneratorHelpers.IsAbstractStmt(@class)) if (IsAbstractType(@class) || IsAbstractDecl(@class) || IsAbstractStmt(@class))
@class.IsAbstract = true; @class.IsAbstract = true;
Check(@class); //
// Statements
//
foreach (var @base in @class.Bases) 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) public override bool VisitClassTemplateDecl(ClassTemplate template)
{ {
Check(template);
return base.VisitClassTemplateDecl(template); return base.VisitClassTemplateDecl(template);
} }
public override bool VisitTypeAliasTemplateDecl(TypeAliasTemplate template) public override bool VisitTypeAliasTemplateDecl(TypeAliasTemplate template)
{ {
Check(template);
return base.VisitTypeAliasTemplateDecl(template); return base.VisitTypeAliasTemplateDecl(template);
} }
public override bool VisitProperty(Property property) 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(); property.ExplicitlyIgnore();
return base.VisitProperty(property); return true;
} }
public override bool VisitEnumDecl(Enumeration @enum) public override bool VisitEnumDecl(Enumeration @enum)
{ {
if (AlreadyVisited(@enum)) if (!base.VisitEnumDecl(@enum))
return false; return false;
if (@enum.Name == "APFloatSemantics") if (@enum.Name == "APFloatSemantics")
@ -464,7 +755,7 @@ namespace CppSharp
RemoveEnumItemsPrefix(@enum); RemoveEnumItemsPrefix(@enum);
return base.VisitEnumDecl(@enum); return true;
} }
private void RemoveEnumItemsPrefix(Enumeration @enum) private void RemoveEnumItemsPrefix(Enumeration @enum)
@ -586,7 +877,7 @@ namespace CppSharp
public override bool VisitClassDecl(Class @class) public override bool VisitClassDecl(Class @class)
{ {
if (!@class.IsGenerated) if (SkipClass(@class))
return false; return false;
GenerateClassSpecifier(@class); GenerateClassSpecifier(@class);
@ -953,6 +1244,7 @@ namespace CppSharp
{ {
Context.Options.GeneratorKind = GeneratorKind.CPlusPlus; Context.Options.GeneratorKind = GeneratorKind.CPlusPlus;
CTypePrinter.PushScope(TypePrintScopeKind.Local); CTypePrinter.PushScope(TypePrintScopeKind.Local);
CTypePrinter.PushContext(TypePrinterContextKind.Normal);
GenerateFilePreamble(CommentKind.BCPL); GenerateFilePreamble(CommentKind.BCPL);
NewLine(); NewLine();
@ -1042,7 +1334,12 @@ namespace CppSharp
return $"{typeName}()"; return $"{typeName}()";
if (property.Type.TryGetEnum(out Enumeration @enum)) 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 $"{GetQualifiedName(@enum)}::{@enum.Items.First().Name}";
}
return "0"; return "0";
} }

243
src/CppParser/Bootstrap/CodeGeneratorHelpers.cs

@ -9,6 +9,44 @@ using CppSharp.Passes;
namespace CppSharp 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 class CodeGeneratorHelpers
{ {
internal static CppTypePrinter CppTypePrinter; internal static CppTypePrinter CppTypePrinter;
@ -31,6 +69,17 @@ namespace CppSharp
or "OverloadExpr" or "OverloadExpr"
or "CoroutineSuspendExpr"; 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) public static bool SkipProperty(Property property, bool skipBaseCheck = false)
{ {
if (!property.IsGenerated) if (!property.IsGenerated)
@ -61,11 +110,22 @@ namespace CppSharp
var typeName = property.Type.Visit(CppTypePrinter).Type; 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. // Statement properties.
// //
if (typeName.Contains("LabelDecl") || /*if (typeName.Contains("LabelDecl") ||
typeName.Contains("VarDecl") || typeName.Contains("VarDecl") ||
typeName.Contains("Token") || typeName.Contains("Token") ||
typeName.Contains("CapturedDecl") || typeName.Contains("CapturedDecl") ||
@ -77,7 +137,7 @@ namespace CppSharp
typeName.Contains("NestedNameSpecifierLoc") || typeName.Contains("NestedNameSpecifierLoc") ||
typeName.Contains("DeclarationNameInfo") || typeName.Contains("DeclarationNameInfo") ||
typeName.Contains("DeclGroupRef")) typeName.Contains("DeclGroupRef"))
return true; return true;*/
// //
// Expressions // Expressions
@ -209,11 +269,6 @@ namespace CppSharp
if (typeName.Contains("StorageDuration")) if (typeName.Contains("StorageDuration"))
return true; return true;
// General properties.
if (typeName.Contains("_iterator") ||
typeName.Contains("_range"))
return true;
if (typeName.Contains("ArrayRef")) if (typeName.Contains("ArrayRef"))
return true; return true;
@ -246,7 +301,7 @@ namespace CppSharp
public static bool SkipMethod(Method method) public static bool SkipMethod(Method method)
{ {
if (method.Ignore) if (method.IsGenerated)
return true; return true;
var @class = method.Namespace as Class; var @class = method.Namespace as Class;
@ -335,8 +390,14 @@ namespace CppSharp
if (kind == GeneratorKind.CPlusPlus) if (kind == GeneratorKind.CPlusPlus)
{ {
if (Generators.C.CCodeGenerator.IsReservedKeyword(name)) if (name == "inline")
{
name = "isInline";
}
else if (Generators.C.CCodeGenerator.IsReservedKeyword(name))
{
name = $"_{name}"; name = $"_{name}";
}
} }
else if (kind == GeneratorKind.CSharp) else if (kind == GeneratorKind.CSharp)
{ {
@ -372,7 +433,7 @@ namespace CppSharp
TypePrinter typePrinter) TypePrinter typePrinter)
{ {
var qualifiedType = new QualifiedType(type); var qualifiedType = new QualifiedType(type);
if (qualifiedType.Type.IsPointerTo(out TagType tagType)) if (qualifiedType.Type.IsPointerTo(out TagType _))
qualifiedType = qualifiedType.StripConst(); qualifiedType = qualifiedType.StripConst();
var typeName = qualifiedType.Type.Visit(typePrinter).Type; 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; return typeName;
} }
public static AST.Type GetIteratorType(Method method) public static AST.Type GetIteratorType(Method method)
{ {
var retType = method.ReturnType.Type; var retType = method.ReturnType.Type.Desugar();
TemplateSpecializationType templateSpecType;
TypedefType typedefType;
TypedefNameDecl typedefNameDecl;
if (retType is TemplateSpecializationType) if (retType is TemplateSpecializationType templateSpecType)
{ retType = templateSpecType.Arguments[0].Type.Type.Desugar();
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;
}
var iteratorType = typedefNameDecl.Type; if (retType.IsPointerTo(out PointerType pointee))
if (iteratorType.IsPointerTo(out PointerType pointee)) retType = pointee;
iteratorType = iteratorType.GetPointee();
return iteratorType; return retType;
} }
public static string GetIteratorTypeName(AST.Type iteratorType, public static string GetIteratorTypeName(AST.Type iteratorType, TypePrinter typePrinter)
TypePrinter typePrinter)
{ {
if (iteratorType.IsPointer()) if (iteratorType.IsPointer())
iteratorType = iteratorType.GetFinalPointee(); iteratorType = iteratorType.GetFinalPointee();
@ -494,7 +517,8 @@ namespace CppSharp
else if (iteratorTypeName.Contains("StmtIterator")) else if (iteratorTypeName.Contains("StmtIterator"))
iteratorTypeName = "Stmt"; iteratorTypeName = "Stmt";
else if (iteratorTypeName.Contains("CastIterator")) else if (iteratorTypeName.Contains("CastIterator") ||
iteratorTypeName.Contains("DeclContext::"))
{ {
if (iteratorType is TypedefType typedefType) if (iteratorType is TypedefType typedefType)
iteratorType = typedefType.Declaration.Type; iteratorType = typedefType.Declaration.Type;
@ -509,9 +533,6 @@ namespace CppSharp
iteratorTypeName = CleanClangNamespaceFromName(iteratorTypeName); iteratorTypeName = CleanClangNamespaceFromName(iteratorTypeName);
} }
if (iteratorTypeName == "Decl")
iteratorTypeName = "Declaration";
if (typePrinter is CppTypePrinter) if (typePrinter is CppTypePrinter)
return $"{iteratorTypeName}*"; return $"{iteratorTypeName}*";
@ -547,5 +568,109 @@ namespace CppSharp
a[0] = char.ToUpper(a[0]); a[0] = char.ToUpper(a[0]);
return new string(a); 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"));
}
} }
} }

221
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<Declaration> 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<Declaration> 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<Declaration> declarations)
: base(context, declarations)
{
}
public override string BaseTypeName => "Decl";
public override bool IsAbstractASTNode(Class kind)
{
return IsAbstractDecl(kind);
}
protected override void GenerateVisitorSwitch(IEnumerable<string> classes)
{
WriteLine($"switch({ParamName}.DeclKind)");
WriteOpenBraceAndIndent();
GenerateSwitchCases(classes);
UnindentAndWriteCloseBrace();
}
private void GenerateSwitchCases(IEnumerable<string> 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());");
}
}
}

55
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<string> _processedClasses = new();
public void ValidateInheritance(IEnumerable<Declaration> declarations)
{
foreach (var decl in declarations.OfType<Class>())
{
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();
}
}
}
}
}

104
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<Declaration> 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<Declaration> 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;
}
}
}

2
src/CppParser/Bootstrap/Properties/launchSettings.json

@ -2,7 +2,7 @@
"profiles": { "profiles": {
"CppSharp.Parser.Bootstrap": { "CppSharp.Parser.Bootstrap": {
"commandName": "Project", "commandName": "Project",
"nativeDebugging": true "nativeDebugging": false
} }
} }
} }

24
src/CppParser/Bootstrap/StmtCodeGenerators.cs

@ -66,8 +66,7 @@ namespace CppSharp
continue; continue;
var iteratorType = GetIteratorType(method); var iteratorType = GetIteratorType(method);
string iteratorTypeName = GetIteratorTypeName(iteratorType, string iteratorTypeName = GetIteratorTypeName(iteratorType, CodeGeneratorHelpers.CppTypePrinter);
CodeGeneratorHelpers.CppTypePrinter);
WriteLine($"VECTOR({iteratorTypeName}, {method.Name})"); WriteLine($"VECTOR({iteratorTypeName}, {method.Name})");
} }
@ -114,6 +113,12 @@ namespace CppSharp
return true; return true;
} }
//PushBlock(BlockKind.Class, @class);
//GenerateDeclarationCommon(@class);
//GenerateClassSpecifier(@class);
WriteLine($"{@class.Name}::{@class.Name}()"); WriteLine($"{@class.Name}::{@class.Name}()");
var stmtMember = isStmt ? "stmtClass" : @class.BaseClass.Name; var stmtMember = isStmt ? "stmtClass" : @class.BaseClass.Name;
var stmtClass = IsAbstractStmt(@class) ? "NoStmt" : @class.Name; var stmtClass = IsAbstractStmt(@class) ? "NoStmt" : @class.Name;
@ -301,9 +306,22 @@ namespace CppSharp
{ {
walkMethod = "WalkStatement"; walkMethod = "WalkStatement";
} }
else if (iteratorTypeName.Contains("Attr"))
{
walkMethod = "WalkDeclaration";
}
else if (iteratorTypeName.Contains("CXXBaseSpecifier"))
{
walkMethod = "WalkDeclaration";
}
else if (iteratorTypeName.Contains("CXXCtorInitializer"))
{
walkMethod = "WalkDeclaration";
}
else else
{ {
throw new NotImplementedException(); //throw new NotImplementedException();
walkMethod = "WalkDeclaration";
} }
WriteLine("auto _ES = {0}{1}(_E);", isBaseType ? string.Empty : $"(AST::{iteratorTypeName})", walkMethod); WriteLine("auto _ES = {0}{1}(_E);", isBaseType ? string.Empty : $"(AST::{iteratorTypeName})", walkMethod);

323
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<Declaration> 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<Declaration> 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<Declaration> declarations)
: base(context, declarations)
{
}
public override string BaseTypeName => "Type";
public override bool IsAbstractASTNode(Class kind)
{
return IsAbstractType(kind);
}
protected override void GenerateVisitorSwitch(IEnumerable<string> classes)
{
WriteLine($"switch({ParamName}.DeclKind)");
WriteOpenBraceAndIndent();
GenerateSwitchCases(classes);
UnindentAndWriteCloseBrace();
}
public void GenerateSwitchCases(IEnumerable<string> 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());");
}
}
}

9
src/CppParser/Decl.h

@ -566,15 +566,6 @@ namespace AST {
VECTOR(LayoutBase, Bases) VECTOR(LayoutBase, Bases)
}; };
enum class TagKind
{
Struct,
Interface,
Union,
Class,
Enum
};
class CS_API Class : public DeclarationContext class CS_API Class : public DeclarationContext
{ {
public: public:

21
src/CppParser/Types.h

@ -10,6 +10,7 @@
#include "Helpers.h" #include "Helpers.h"
namespace CppSharp { namespace CppParser { namespace AST { namespace CppSharp { namespace CppParser { namespace AST {
class Expr;
enum class TypeKind enum class TypeKind
{ {
@ -34,6 +35,15 @@ namespace CppSharp { namespace CppParser { namespace AST {
Vector Vector
}; };
enum class TagKind
{
Struct,
Interface,
Union,
Class,
Enum
};
#define DECLARE_TYPE_KIND(kind) \ #define DECLARE_TYPE_KIND(kind) \
kind##Type(); kind##Type();
@ -88,6 +98,17 @@ namespace CppSharp { namespace CppParser { namespace AST {
long elementSize; long elementSize;
}; };
class CS_API VariableArrayType : public ArrayType
{
public:
VariableArrayType()
{
sizeType = ArraySize::Variable;
}
Expr* sizeExpr = nullptr;
};
class Parameter; class Parameter;
enum class CallingConvention enum class CallingConvention

4
src/Generator/Generators/CodeGenerator.cs

@ -427,7 +427,7 @@ namespace CppSharp.Generators
public virtual bool VisitClassTemplateDecl(ClassTemplate template) public virtual bool VisitClassTemplateDecl(ClassTemplate template)
{ {
throw new NotImplementedException(); return true;
} }
public virtual bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization) public virtual bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization)
@ -437,7 +437,7 @@ namespace CppSharp.Generators
public virtual bool VisitFunctionTemplateDecl(FunctionTemplate template) public virtual bool VisitFunctionTemplateDecl(FunctionTemplate template)
{ {
throw new NotImplementedException(); return true;
} }
public virtual bool VisitFunctionTemplateSpecializationDecl(FunctionTemplateSpecialization specialization) public virtual bool VisitFunctionTemplateSpecializationDecl(FunctionTemplateSpecialization specialization)

Loading…
Cancel
Save