From 8afc2b3e1e1348825ffaffcccf86e6ffeae0c19c Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Thu, 14 Dec 2023 08:25:28 +0200 Subject: [PATCH 01/13] Registrable: add folder + start development --- .../Lua/Sol/LuaSolGenerationContext.cs | 10 + .../Registrable/Lua/Sol/LuaSolGenerator.cs | 37 + .../Lua/Sol/LuaSolGeneratorOptions.cs | 12 + .../Registrable/Lua/Sol/LuaSolHeaders.cs | 163 +++++ .../Lua/Sol/LuaSolNamingStrategy.cs | 10 + .../Registrable/Lua/Sol/LuaSolSources.cs | 643 ++++++++++++++++++ .../Registrable/Lua/Sol/LuaSolTypePrinter.cs | 12 + .../RegistrableGeneratorContext.cs | 126 ++++ .../RegistrableGeneratorOptions.cs | 50 ++ .../Registrable/RegistrableInfoEntries.cs | 6 + .../Registrable/RegistrableNamingStrategy.cs | 402 +++++++++++ .../Generators/Registrable/Utils/FQNOption.cs | 44 ++ .../Generators/Registrable/Utils/InfoEntry.cs | 65 ++ .../Generators/Registrable/Utils/InfoMap.cs | 16 + .../Registrable/Utils/InfoMapStack.cs | 71 ++ .../Utils/TemplateParameterOption.cs | 22 + .../Generators/Registrable/Utils/Utils.cs | 19 + 17 files changed, 1708 insertions(+) create mode 100644 src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerationContext.cs create mode 100644 src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs create mode 100644 src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs create mode 100644 src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs create mode 100644 src/Generator/Generators/Registrable/Lua/Sol/LuaSolNamingStrategy.cs create mode 100644 src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs create mode 100644 src/Generator/Generators/Registrable/Lua/Sol/LuaSolTypePrinter.cs create mode 100644 src/Generator/Generators/Registrable/RegistrableGeneratorContext.cs create mode 100644 src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs create mode 100644 src/Generator/Generators/Registrable/RegistrableInfoEntries.cs create mode 100644 src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs create mode 100644 src/Generator/Generators/Registrable/Utils/FQNOption.cs create mode 100644 src/Generator/Generators/Registrable/Utils/InfoEntry.cs create mode 100644 src/Generator/Generators/Registrable/Utils/InfoMap.cs create mode 100644 src/Generator/Generators/Registrable/Utils/InfoMapStack.cs create mode 100644 src/Generator/Generators/Registrable/Utils/TemplateParameterOption.cs create mode 100644 src/Generator/Generators/Registrable/Utils/Utils.cs diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerationContext.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerationContext.cs new file mode 100644 index 000000000..60811553f --- /dev/null +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerationContext.cs @@ -0,0 +1,10 @@ +namespace CppSharp.Generators.Registrable.Lua.Sol +{ + public class LuaSolGenerationContext : RegistrableGeneratorContext + { + public LuaSolGenerationContext() + : base() + { + } + } +} diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs new file mode 100644 index 000000000..db7766ad0 --- /dev/null +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs @@ -0,0 +1,37 @@ +using CppSharp.AST; +using System.Collections.Generic; + +namespace CppSharp.Generators.Registrable.Lua.Sol +{ + + public class LuaSolGenerator : Generator + { + public const string Id = "Lua::Sol"; + public static readonly GeneratorKind Kind = new(Id, "lua::sol", typeof(LuaSolGenerator), typeof(LuaSolTypePrinter), new[] { "lua::sol" }); + + public LuaSolGeneratorOptions GeneratorOptions + { + get; + } + + public LuaSolGenerator(BindingContext context) : base(context) + { + GeneratorOptions = new LuaSolGeneratorOptions(this); + } + + public override List<CodeGenerator> Generate(IEnumerable<TranslationUnit> units) + { + var outputs = new List<CodeGenerator>(); + + var header = new LuaSolHeaders(this, units); + outputs.Add(header); + + var source = new LuaSolSources(this, units); + outputs.Add(source); + + return outputs; + } + + public override bool SetupPasses() => true; + } +} diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs new file mode 100644 index 000000000..158cb47bb --- /dev/null +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs @@ -0,0 +1,12 @@ +namespace CppSharp.Generators.Registrable.Lua.Sol +{ + public class LuaSolGeneratorOptions : RegistrableGeneratorOptions + { + public LuaSolNamingStrategy NamingStrategy; + + public LuaSolGeneratorOptions(LuaSolGenerator generator) : base() + { + NamingStrategy = new LuaSolNamingStrategy(generator); + } + } +} diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs new file mode 100644 index 000000000..78599525f --- /dev/null +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs @@ -0,0 +1,163 @@ +using System.Collections.Generic; +using CppSharp.AST; + +namespace CppSharp.Generators.Registrable.Lua.Sol +{ + public class LuaSolHeaders : LuaSolSources + { + public LuaSolHeaders(LuaSolGenerator generator, IEnumerable<TranslationUnit> units) + : base(generator, units) + { + } + + public override string FileExtension => "h"; + + public override void Process() + { + GenerateFilePreamble(CommentKind.BCPL); + + PushBlock(); + WriteLine("#pragma once"); + PopBlock(NewLineKind.BeforeNextBlock); + + //NewLine(); + //PushBlock(BlockKind.Includes); + //GenerateIncludes(); + //PopBlock(NewLineKind.BeforeNextBlock); + + TranslationUnit.Visit(this); + + //PushBlock(BlockKind.Footer); + //PopBlock(); + + //PushBlock(BlockKind.Class); + //PopBlock(NewLineKind.IfNotEmpty); + + //RegistrableGeneratorContext mycontext = new RegistrableGeneratorContext(); + //string a = (string)mycontext[new InfoEntry("")].Pop(); + } + + #region TranslationUnit + + public virtual void GenerateTranslationUnitNamespaceBegin(TranslationUnit translationUnit) + { + PushBlock(BlockKind.Namespace); + WriteLine($"namespace {TranslationUnit.Module.OutputNamespace} {{"); + } + + public virtual void GenerateTranslationUnitNamespaceEnd(TranslationUnit translationUnit) + { + WriteLine($"}} // namespace {TranslationUnit.Module.OutputNamespace}"); + PopBlock(); + } + + public virtual void GenerateTranslationUnitRegistrationFunctionDeclaration(TranslationUnit translationUnit) + { + NewLine(); + WriteLine(GetTranslationUnitRegistrationFunctionSignature(translationUnit)); + NewLine(); + } + + public virtual void GenerateTranslationUnit(TranslationUnit translationUnit) + { + GenerateTranslationUnitNamespaceBegin(translationUnit); + GenerateTranslationUnitRegistrationFunctionDeclaration(translationUnit); + GenerateTranslationUnitNamespaceEnd(translationUnit); + } + + public virtual bool CanGenerateTranslationUnit(TranslationUnit unit) + { + if (AlreadyVisited(unit)) + { + return false; + } + return true; + } + + public override bool VisitTranslationUnit(TranslationUnit unit) + { + if (!CanGenerateTranslationUnit(unit)) + { + return false; + } + + GenerateTranslationUnit(unit); + + return true; + } + + #endregion + + // + + public virtual void GenerateMain() + { + VisitNamespace(TranslationUnit); + } + + public virtual void GenerateIncludes() + { + foreach (var include in Generator.GeneratorOptions.CommonIncludes) + { + WriteLineIndent(include.ToString()); + } + } + + //public override bool VisitNamespace(Namespace @namespace) + //{ + // base.VisitNamespace(@namespace); + // return true; + //} + + public override bool VisitMethodDecl(Method method) + { + return true; + } + + public override bool VisitFunctionDecl(Function function) + { + //if (FunctionIsTemplate(function)) + //{ + // Console.WriteLine("test"); + //} + return true; + } + + public override bool VisitClassTemplateDecl(ClassTemplate template) + { + return true; + } + + public override bool VisitVariableDecl(Variable variable) + { + return true; + } + + public override bool VisitTypeAliasTemplateDecl(TypeAliasTemplate typeAliasTemplate) + { + return true; + } + + public override bool VisitTypedefNameDecl(TypedefNameDecl typedef) + { + return true; + } + + public override bool VisitFunctionTemplateDecl(FunctionTemplate template) + { + return true; + } + + public static bool FunctionIsTemplate(Function function) + { + foreach (var template in function.Namespace.Templates) + { + if (template.TemplatedDecl == function) + { + return true; + } + } + return false; + } + } +} diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolNamingStrategy.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolNamingStrategy.cs new file mode 100644 index 000000000..2f26269ba --- /dev/null +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolNamingStrategy.cs @@ -0,0 +1,10 @@ +namespace CppSharp.Generators.Registrable.Lua.Sol +{ + public class LuaSolNamingStrategy : RegistrableNamingStrategy<LuaSolGenerator> + { + public LuaSolNamingStrategy(LuaSolGenerator generator) + : base(generator) + { + } + } +} diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs new file mode 100644 index 000000000..410e3f417 --- /dev/null +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -0,0 +1,643 @@ +using CppSharp.AST; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace CppSharp.Generators.Registrable.Lua.Sol +{ + public class LuaSolSources : CodeGenerator + { + protected LuaSolGenerator Generator { get; } + protected LuaSolGenerationContext GenerationContext { get; } + protected LuaSolNamingStrategy NamingStrategy => Generator.GeneratorOptions.NamingStrategy; + + public LuaSolSources(LuaSolGenerator generator, IEnumerable<TranslationUnit> units) + : base(generator.Context, units) + { + Generator = generator; + GenerationContext = new LuaSolGenerationContext(); + } + + public override string FileExtension { get { return "cpp"; } } + + protected virtual bool TemplateAllowed { get { return false; } } + + protected bool NonTemplateAllowed { get { return !TemplateAllowed || GenerationContext.PeekTemplateLevel() != 0; } } + + public override void Process() + { + GenerateFilePreamble(CommentKind.BCPL); + + PushBlock(BlockKind.Includes); + var file = Context.Options.GetIncludePath(TranslationUnit); + WriteLine($"#include \"{file}\""); + + NewLine(); + PopBlock(); + + TranslationUnit.Visit(this); + + PushBlock(BlockKind.Footer); + PopBlock(); + } + + public virtual void GenerateDeclarationGlobalStateRegistration(Declaration declaration) + { + if (declaration.Access != AccessSpecifier.Protected) + { + if (declaration.OriginalNamespace is not Class) + { + Write(NamingStrategy.GetBindingContext(declaration, GenerationContext)); + } + else + { + Write($"{NamingStrategy.GetRootContextName(GenerationContext)}[{NamingStrategy.GetBindingIdValue(declaration.Namespace, GenerationContext)}]"); + } + Write($"[{NamingStrategy.GetRegistrationNameQuoted(declaration)}] = "); + Write($"{NamingStrategy.GetRootContextName(GenerationContext)}[{NamingStrategy.GetBindingIdName(declaration)}];"); + NewLine(); + } + } + + public virtual void GenerateDeclarationContainerList(DeclarationContext declaration) + { + List<Declaration> declarations = declaration.Declarations.Where(declaration => declaration is Namespace || declaration is Class || declaration is Enumeration).ToList(); + declarations.Sort((x, y) => x.LineNumberStart.CompareTo(y.LineNumberStart)); + foreach (var item in declarations) + { + item.Visit(this); + }; + } + + #region TranslationUnit + + public virtual string GetTranslationUnitRegistrationFunctionSignature(TranslationUnit translationUnit) + { + StringBuilder builder = new StringBuilder(); + builder.Append("void "); + builder.Append(Generator.GeneratorOptions.NamingStrategy.GetRegistrationFunctionName(translationUnit)); + builder.Append("(::sol::state_view& state) {"); + return builder.ToString(); + } + + public virtual void GenerateTranslationUnitNamespaceBegin(TranslationUnit translationUnit) + { + PushBlock(BlockKind.Namespace); + WriteLine($"namespace {TranslationUnit.Module.OutputNamespace} {{"); + } + + public virtual void GenerateTranslationUnitNamespaceEnd(TranslationUnit translationUnit) + { + WriteLine($"}} // namespace {TranslationUnit.Module.OutputNamespace}"); + PopBlock(); + } + + public virtual void GenerateTranslationUnitRegistrationFunctionBegin(TranslationUnit translationUnit) + { + PushBlock(BlockKind.Function); + NewLine(); + WriteLine(GetTranslationUnitRegistrationFunctionSignature(translationUnit)); + Indent(); + } + + public virtual void GenerateTranslationUnitRegistrationFunctionBody(TranslationUnit translationUnit) + { + GenerateDeclarationContainerList(translationUnit); + } + + public virtual void GenerateTranslationUnitRegistrationFunctionEnd(TranslationUnit translationUnit) + { + Unindent(); + WriteLine("}"); + NewLine(); + PopBlock(NewLineKind.BeforeNextBlock); + } + + public virtual void GenerateTranslationUnit(TranslationUnit translationUnit) + { + GenerateTranslationUnitNamespaceBegin(translationUnit); + GenerateTranslationUnitRegistrationFunctionBegin(translationUnit); + GenerateTranslationUnitRegistrationFunctionBody(translationUnit); + GenerateTranslationUnitRegistrationFunctionEnd(translationUnit); + GenerateTranslationUnitNamespaceEnd(translationUnit); + } + + public virtual bool CanGenerateTranslationUnit(TranslationUnit unit) + { + if (AlreadyVisited(unit)) + { + return false; + } + return true; + } + + public override bool VisitTranslationUnit(TranslationUnit unit) + { + if (!CanGenerateTranslationUnit(unit)) + { + return false; + } + + GenerateTranslationUnit(unit); + + return true; + } + + #endregion + + #region Namespace + + public virtual void GenerateNamespaceDebugName(Namespace @namespace) + { + WriteLine($"/* {NamingStrategy.GetFullyQualifiedName(@namespace, FQNOption.IgnoreNone)} */"); + } + + public virtual void GenerateNamespaceHeader(Namespace @namespace) + { + WriteLine("{"); + Indent(); + } + + public virtual void GenerateNamespaceBegin(Namespace @namespace) + { + Write($"auto {NamingStrategy.GetBindingName(@namespace)} = "); + Write(NamingStrategy.GetBindingContextNamespacePredicate( + NamingStrategy.GetBindingContext(@namespace, GenerationContext), + @namespace.Name) + ); + WriteLine(";"); + } + + public virtual void GenerateNamespaceBody(Namespace @namespace) + { + GenerateNamespaceDeclarationList(@namespace, DetachmentOption.Off); + } + + public virtual void GenerateNamespaceDeclarationList(Namespace @namespace, DetachmentOption detachment) + { + if (detachment == DetachmentOption.Off) + { + GenerateNamespaceFunctions(@namespace); + GenerateNamespaceVariables(@namespace); + } + else + { + GenerateNamespaceContainerList(@namespace); + GenerateNamespaceTemplates(@namespace); + GenerateNamespaceTypedefs(@namespace); + GenerateNamespaceFunctions(@namespace); + GenerateNamespaceVariables(@namespace); + } + } + + public virtual void GenerateNamespaceContainerList(Namespace @namespace) + { + GenerateDeclarationContainerList(@namespace); + } + + public virtual void GenerateNamespaceTemplates(Namespace @namespace) + { + } + + public virtual void GenerateNamespaceTypedefs(Namespace @namespace) + { + } + + public virtual void GenerateNamespaceFunctions(Namespace @namespace) + { + } + + public virtual void GenerateNamespaceVariables(Namespace @namespace) + { + } + + public virtual void GenerateNamespaceEnd(Namespace @namespace) + { + GenerateNamespaceDeclarationList(@namespace, DetachmentOption.On); + } + + public virtual void GenerateNamespaceGlobalStateRegistration(Namespace @namespace) + { + } + + public virtual void GenerateNamespaceFooter(Namespace @namespace) + { + Unindent(); + WriteLine("}"); + } + + public virtual void GenerateNamespace(Namespace @namespace) + { + GenerateNamespaceDebugName(@namespace); + GenerateNamespaceHeader(@namespace); + GenerateNamespaceBegin(@namespace); + GenerateNamespaceBody(@namespace); + GenerateNamespaceEnd(@namespace); + GenerateNamespaceGlobalStateRegistration(@namespace); + GenerateNamespaceFooter(@namespace); + } + + public virtual bool CanGenerateNamespace(Namespace @namespace) + { + // if not self:isNonTemplateAllowed(context) then + // return true + // end + if (AlreadyVisited(@namespace)) + { + return false; + } + else if (@namespace.Access != AccessSpecifier.Public) + { + return false; + } + return @namespace.IsGenerated; + } + + public override bool VisitNamespace(Namespace @namespace) + { + if (!CanGenerateNamespace(@namespace)) + { + return false; + } + + GenerateNamespace(@namespace); + + return true; + } + + #endregion + + #region Enumeration + + public virtual void GenerateEnumDeclItem(Enumeration enumeration, Enumeration.Item item) + { + Write(","); + NewLine(); + Write($"\"{item.Name}\", {NamingStrategy.GetFullyQualifiedName(item, FQNOption.IgnoreNone)}"); + } + + public virtual void GenerateEnumDeclItemList(Enumeration enumeration, List<Enumeration.Item> items) + { + foreach (var item in items) + { + GenerateEnumDeclItem(enumeration, item); + } + } + + #region Enumeration Anonymous + + public virtual void GenerateEnumDeclAnonymousItem(Enumeration enumeration, Enumeration.Item item) + { + WriteLine($"{NamingStrategy.GetRootContextName(GenerationContext)}[\"{item.Name}\"] = {item.OriginalName};"); + } + + public virtual void GenerateEnumDeclAnonymousItemList(Enumeration enumeration, List<Enumeration.Item> items) + { + foreach (var item in items) + { + GenerateEnumDeclAnonymousItem(enumeration, item); + } + } + + public virtual void GenerateEnumDeclAnonymous(Enumeration enumeration) + { + GenerateEnumDeclAnonymousItemList(enumeration, enumeration.Items); + } + + #endregion + + #region Enumeration Non Scoped + + public virtual void GenerateEnumDeclNonScoped(Enumeration enumeration) + { + GenerateEnumDeclScoped(enumeration); + GenerateEnumDeclAnonymous(enumeration); + } + + #endregion + + #region Enumeration Scoped + + public virtual void GenerateEnumDeclScopedDebugName(Enumeration enumeration) + { + WriteLine($"/* {NamingStrategy.GetFullyQualifiedName(enumeration, FQNOption.IgnoreNone)} */"); + } + + public virtual void GenerateEnumDeclScopedHeader(Enumeration enumeration) + { + WriteLine("{"); + Indent(); + } + + public virtual void GenerateEnumDeclScopedBindingIdName(Enumeration enumeration) + { + WriteLine($"auto {NamingStrategy.GetBindingIdName(enumeration)} = {NamingStrategy.GetBindingIdValue(enumeration, GenerationContext)};"); + } + + public virtual void GenerateEnumDeclScopedBegin(Enumeration enumeration) + { + WriteLine($"auto {NamingStrategy.GetBindingName(enumeration)} = {NamingStrategy.GetRootContextName(GenerationContext)}.new_enum<>("); + Indent(); + Write(NamingStrategy.GetBindingIdName(enumeration)); + } + + public virtual void GenerateEnumDeclScopedItemList(Enumeration enumeration) + { + GenerateEnumDeclItemList(enumeration, enumeration.Items); + } + + public virtual void GenerateEnumDeclScopedBody(Enumeration enumeration) + { + GenerateEnumDeclScopedItemList(enumeration); + GenerateEnumDeclScopedDeclarationList(enumeration, DetachmentOption.Off); + } + + public virtual void GenerateEnumDeclScopedDeclarationList(Enumeration enumeration, DetachmentOption detachment) + { + if (detachment == DetachmentOption.Off) + { + GenerateEnumDeclScopedFunctions(enumeration); + GenerateEnumDeclScopedVariables(enumeration); + } + else + { + GenerateEnumDeclScopedContainerList(enumeration); + GenerateEnumDeclScopedTemplates(enumeration); + GenerateEnumDeclScopedTypedefs(enumeration); + GenerateEnumDeclScopedFunctions(enumeration); + GenerateEnumDeclScopedVariables(enumeration); + } + } + + public virtual void GenerateEnumDeclScopedContainerList(Enumeration enumeration) + { + GenerateDeclarationContainerList(enumeration); + } + + public virtual void GenerateEnumDeclScopedTemplates(Enumeration enumeration) + { + } + + public virtual void GenerateEnumDeclScopedTypedefs(Enumeration enumeration) + { + } + + public virtual void GenerateEnumDeclScopedFunctions(Enumeration enumeration) + { + } + + public virtual void GenerateEnumDeclScopedVariables(Enumeration enumeration) + { + } + + public virtual void GenerateEnumDeclScopedEnd(Enumeration enumeration) + { + Unindent(); + NewLine(); + WriteLine(");"); + GenerateEnumDeclScopedDeclarationList(enumeration, DetachmentOption.On); + } + + public virtual void GenerateEnumDeclScopedGlobalStateRegistration(Enumeration enumeration) + { + GenerateDeclarationGlobalStateRegistration(enumeration); + } + + public virtual void GenerateEnumDeclScopedFooter(Enumeration enumeration) + { + Unindent(); + WriteLine("}"); + } + + public virtual void GenerateEnumDeclScoped(Enumeration enumeration) + { + GenerateEnumDeclScopedDebugName(enumeration); + GenerateEnumDeclScopedHeader(enumeration); + GenerateEnumDeclScopedBindingIdName(enumeration); + GenerateEnumDeclScopedBegin(enumeration); + GenerateEnumDeclScopedBody(enumeration); + GenerateEnumDeclScopedEnd(enumeration); + GenerateEnumDeclScopedGlobalStateRegistration(enumeration); + GenerateEnumDeclScopedFooter(enumeration); + } + + #endregion + + public virtual void GenerateEnumDecl(Enumeration enumeration) + { + if (enumeration.IsScoped) + { + GenerateEnumDeclScoped(enumeration); + } + else + { + if (string.IsNullOrEmpty(enumeration.OriginalName)) + { + GenerateEnumDeclAnonymous(enumeration); + } + else + { + GenerateEnumDeclNonScoped(enumeration); + } + } + } + + public virtual bool CanGenerateEnumDecl(Enumeration enumeration) + { + // if not self:isNonTemplateAllowed(context) then + // return true + // end + if (AlreadyVisited(enumeration)) + { + return false; + } + else if (enumeration.Access != AccessSpecifier.Public) + { + return false; + } + return enumeration.IsGenerated; + } + + public override bool VisitEnumDecl(Enumeration enumeration) + { + if (!CanGenerateEnumDecl(enumeration)) + { + return false; + } + + GenerateEnumDecl(enumeration); + + return true; + } + + #endregion + + #region Class + + public virtual void GenerateClassDeclDebugName(Class @class) + { + WriteLine($"/* {NamingStrategy.GetFullyQualifiedName(@class, FQNOption.IgnoreNone)} */"); + } + + public virtual void GenerateClassDeclHeader(Class @class) + { + WriteLine("{"); + Indent(); + } + + public virtual void GenerateClassDeclBindingIdName(Class @class) + { + WriteLine($"auto {NamingStrategy.GetBindingIdName(@class)} = {NamingStrategy.GetBindingIdValue(@class, GenerationContext)};"); + } + + public virtual void GenerateClassDeclBegin(Class @class) + { + Write($"auto {NamingStrategy.GetBindingName(@class)} = {NamingStrategy.GetRootContextName(GenerationContext)}."); + if (TemplateAllowed) + { + Write("template "); + } + WriteLine($"new_usertype<{NamingStrategy.GetContextualName(@class, GenerationContext, FQNOption.IgnoreNone)}>("); + Indent(); + Write(NamingStrategy.GetBindingIdName(@class)); + } + + public virtual void GenerateClassDeclBody(Class @class) + { + GenerateClassDeclDeclarationList(@class, DetachmentOption.Off); + } + + public virtual void GenerateClassDeclDeclarationList(Class @class, DetachmentOption detachment) + { + if (detachment == DetachmentOption.Off) + { + GenerateClassDeclFunctions(@class); + GenerateClassDeclVariables(@class); + } + else + { + GenerateClassDeclContainerList(@class); + GenerateClassDeclTemplates(@class); + GenerateClassDeclTypedefs(@class); + GenerateClassDeclFunctions(@class); + GenerateClassDeclVariables(@class); + } + } + + public virtual void GenerateClassDeclContainerList(Class @class) + { + GenerateDeclarationContainerList(@class); + } + + public virtual void GenerateClassDeclTemplates(Class @class) + { + } + + public virtual void GenerateClassDeclTypedefs(Class @class) + { + } + + public virtual void GenerateClassDeclFunctions(Class @class) + { + } + + public virtual void GenerateClassDeclVariables(Class @class) + { + } + + public virtual void GenerateClassDeclEnd(Class @class) + { + Unindent(); + NewLine(); + WriteLine(");"); + GenerateClassDeclDeclarationList(@class, DetachmentOption.On); + } + + public virtual void GenerateClassDeclGlobalStateRegistration(Class @class) + { + GenerateDeclarationGlobalStateRegistration(@class); + } + + public virtual void GenerateClassDeclFooter(Class @class) + { + Unindent(); + WriteLine("}"); + } + + public virtual void GenerateClassDecl(Class @class) + { + GenerateClassDeclDebugName(@class); + GenerateClassDeclHeader(@class); + GenerateClassDeclBindingIdName(@class); + GenerateClassDeclBegin(@class); + GenerateClassDeclBody(@class); + GenerateClassDeclEnd(@class); + GenerateClassDeclGlobalStateRegistration(@class); + GenerateClassDeclFooter(@class); + } + + public virtual bool CanGenerateClassDecl(Class @class) + { + if (AlreadyVisited(@class)) + { + return false; + } + else if (@class.Access != AccessSpecifier.Public) + { + return false; + } + else if (!NonTemplateAllowed) + { + return false; + } + else if (Utils.FindDescribedTemplate(@class) != null) + { + return false; + } + return @class.IsGenerated; + } + + public override bool VisitClassDecl(Class @class) + { + if (!CanGenerateClassDecl(@class)) + { + return false; + } + + GenerateClassDecl(@class); + + return true; + } + + #endregion + + public virtual bool CanGenerateConstructor(Method method) + { + // if not self:isNonTemplateAllowed(context) then + // return true + // end + if (AlreadyVisited(method)) + { + return false; + } + else if (method.Access != AccessSpecifier.Public) + { + return false; + } + return method.IsGenerated; + } + + public virtual void GenerateConstructors(Class @class, IEnumerable<Method> constructors) + { + var isDetach = GenerationContext.PeekIsDetach(); + + if (isDetach == DetachmentOption.Forced) + { + var filteredConstructors = constructors.Where((method) => CanGenerateConstructor(method)); + foreach (var constructor in constructors) + { + } + } + } + } +} diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolTypePrinter.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolTypePrinter.cs new file mode 100644 index 000000000..c6c5b51b3 --- /dev/null +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolTypePrinter.cs @@ -0,0 +1,12 @@ +using CppSharp.Generators; +using CppSharp.Generators.C; + +namespace CppSharp.Generators.Registrable.Lua.Sol +{ + public class LuaSolTypePrinter : CppTypePrinter + { + public LuaSolTypePrinter(BindingContext context) : base(context) + { + } + } +} diff --git a/src/Generator/Generators/Registrable/RegistrableGeneratorContext.cs b/src/Generator/Generators/Registrable/RegistrableGeneratorContext.cs new file mode 100644 index 000000000..25c1c9ce1 --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableGeneratorContext.cs @@ -0,0 +1,126 @@ +namespace CppSharp.Generators.Registrable +{ + public class RegistrableGeneratorContext : InfoMapStack<object> + { + public static readonly InfoEntry IndentLevel = new("CppSharp.Generators.Registrable.IndentLevel"); + public static readonly InfoEntry IsDetach = new("CppSharp.Generators.Registrable.IsDetach"); + public static readonly InfoEntry RootContextName = new("CppSharp.Generators.Registrable.RootContextName"); + public static readonly InfoEntry BindingContext = new("CppSharp.Generators.Registrable.BindingContext"); + public static readonly InfoEntry CppContext = new("CppSharp.Generators.Registrable.CppContext"); + public static readonly InfoEntry SanitizeType = new("CppSharp.Generators.Registrable.SanitizeType"); + public static readonly InfoEntry TypeArgumentsPack = new("CppSharp.Generators.Registrable.TypeArgumentsPack"); + public static readonly InfoEntry Resolvable = new("CppSharp.Generators.Registrable.Resolvable"); + public static readonly InfoEntry TemplateLevel = new("CppSharp.Generators.Registrable.TemplateLevel"); + + public RegistrableGeneratorContext() + { + } + + public DetachmentOption PeekIsDetach() + { + return PeekIsDetach(DetachmentOption.Off); + } + + public DetachmentOption PeekIsDetach(DetachmentOption defaultValue) + { + return Peek(IsDetach, defaultValue); + } + + public void PushIsDetach(DetachmentOption item) + { + Push(IsDetach, item); + } + + public DetachmentOption PopIsDetach() + { + return Pop<DetachmentOption>(IsDetach); + } + + public string PeekRootContextName(string defaultValue = default) + { + return Peek(RootContextName, defaultValue); + } + + public void PushRootContextName(string item) + { + Push(RootContextName, item); + } + + public string PopRootContextName() + { + return Pop<string>(RootContextName); + } + + public string PeekBindingContext(string defaultValue = default) + { + return Peek(BindingContext, defaultValue); + } + + public void PushBindingContext(string item) + { + Push(BindingContext, item); + } + + public string PopBindingContext() + { + return Pop<string>(BindingContext); + } + + public CppContext PeekCppContext(CppContext defaultValue = default) + { + return Peek(CppContext, defaultValue); + } + + public void PushCppContext(CppContext item) + { + Push(CppContext, item); + } + + public CppContext PopCppContext() + { + return Pop<CppContext>(CppContext); + } + + public int PeekTemplateLevel(int defaultValue = default) + { + return Peek(TemplateLevel, defaultValue); + } + + public void PushTemplateLevel(int item) + { + Push(TemplateLevel, item); + } + + public int PopTemplateLevel() + { + return Pop<int>(TemplateLevel); + } + } + + public class CppContext + { + public string FullyQualifiedName { get; set; } + public FQNOption Option { get; set; } + + public string GetFullQualifiedName(FQNOption option) + { + if (!(Option | option).IgnoreTemplateTypenameKeyword) + { + return "typename " + FullyQualifiedName; + } + return FullyQualifiedName; + } + + public string GetFullQualifiedName() + { + return GetFullQualifiedName(FQNOption.IgnoreNone); + } + }; + + public enum DetachmentOption + { + On, + Off, + Forced + } +} diff --git a/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs new file mode 100644 index 000000000..7e7e82d13 --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs @@ -0,0 +1,50 @@ +using CppSharp.Generators.C; +using System.Collections.Generic; + +namespace CppSharp.Generators.Registrable +{ + public abstract class RegistrableGeneratorOptions + { + public delegate string Delegate(string name); + + protected Generator generator; + public virtual ISet<CInclude> CommonIncludes { get; } + public virtual string OutputSubDir { get; } + public Delegate BindingIdNamePredicate { get; } + public Delegate BindingIdValuePredicate { get; } + public Delegate BindingNamePredicate { get; } + + public RegistrableGeneratorOptions() + { + CommonIncludes = new HashSet<CInclude>(); + OutputSubDir = null; + BindingIdNamePredicate = DefaultBindingIdNamePredicate(); + BindingIdValuePredicate = DefaultBindingIdValuePredicate(); + BindingNamePredicate = DefaultBindingNamePredicate(); + } + + public virtual Delegate DefaultBindingIdNamePredicate() + { + return (string name) => + { + return $"_cppbind_id_{name}"; + }; + } + + public virtual Delegate DefaultBindingIdValuePredicate() + { + return (string name) => + { + return $"typeid({name}).name()"; + }; + } + + public virtual Delegate DefaultBindingNamePredicate() + { + return (string name) => + { + return $"_cppbind_{name}"; + }; + } + } +} diff --git a/src/Generator/Generators/Registrable/RegistrableInfoEntries.cs b/src/Generator/Generators/Registrable/RegistrableInfoEntries.cs new file mode 100644 index 000000000..35e384057 --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableInfoEntries.cs @@ -0,0 +1,6 @@ +namespace CppSharp.Generators.Registrable +{ + public class RegistrableInfoEntries + { + } +} diff --git a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs new file mode 100644 index 000000000..9d8bb7f72 --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs @@ -0,0 +1,402 @@ +using CppSharp.AST; +using CppSharp.Generators.C; +using CppSharp.Generators.Registrable.Lua.Sol; +using System.Collections.Generic; +using System.Text; +using System.Xml.Linq; + +namespace CppSharp.Generators.Registrable +{ + public class RegistrableNamingStrategy<T> where T : LuaSolGenerator + { + protected T Generator; + + public RegistrableNamingStrategy(T generator) + { + Generator = generator; + } + + public bool IsNestedTemplate(Declaration declaration) + { + var currentDeclaration = declaration; + while (true) + { + currentDeclaration = currentDeclaration.OriginalNamespace; + if (currentDeclaration != null || currentDeclaration is TranslationUnit) + { + break; + } + if (Utils.FindDescribedTemplate(currentDeclaration) != null) + { + return true; + } + } + return false; + } + + public virtual string PrintClassTemplateParameter(Declaration declaration, TemplateParameterOption option) + { + var builder = new StringBuilder(); + if (declaration is TypeTemplateParameter typeTemplateParameter) + { + if (!option.IgnoreKeyword) + { + builder.Append("typename"); + if (typeTemplateParameter.IsParameterPack) + { + builder.Append("..."); + } + } + if (!string.IsNullOrEmpty(typeTemplateParameter.OriginalName)) + { + if (!option.IgnoreKeyword) + { + builder.Append(' '); + } + if (option.CustomPrefix != null) + { + builder.Append(option.CustomPrefix); + } + builder.Append(typeTemplateParameter.OriginalName); + } + if (!option.IgnoreKeyword) + { + if (!option.IgnoreDefault) + { + if (typeTemplateParameter.DefaultArgument.Type != null) + { + builder.Append(" = "); + builder.Append(typeTemplateParameter.DefaultArgument.Type.Visit(new CppTypePrinter(Generator.Context))); + } + } + } + else + { + if (typeTemplateParameter.IsParameterPack) + { + builder.Append("..."); + } + } + } + else if (declaration is NonTypeTemplateParameter nonTypeTemplateParameter) + { + if (!option.IgnoreKeyword) + { + builder.Append(nonTypeTemplateParameter.Type.Visit(new CppTypePrinter(Generator.Context))); + if (nonTypeTemplateParameter.IsParameterPack) + { + builder.Append("..."); + } + } + if (!string.IsNullOrEmpty(nonTypeTemplateParameter.OriginalName)) + { + if (!option.IgnoreKeyword) + { + builder.Append(' '); + } + if (option.CustomPrefix != null) + { + builder.Append(option.CustomPrefix); + } + builder.Append(nonTypeTemplateParameter.OriginalName); + } + if (!option.IgnoreKeyword) + { + if (!option.IgnoreDefault) + { + if (nonTypeTemplateParameter.DefaultArgument != null) + { + builder.Append(" = "); + builder.Append(nonTypeTemplateParameter.DefaultArgument.ToString()); + } + } + } + else + { + if (nonTypeTemplateParameter.IsParameterPack) + { + builder.Append("..."); + } + } + } + return builder.ToString(); + } + + public virtual string PrintClassTemplateParameters(ClassTemplate classTemplate, bool includeEnclosingBrackets, TemplateParameterOption option) + { + var builder = new StringBuilder(); + builder.Append('<'); + for (int i = 0; i < classTemplate.Parameters.Count; i++) + { + if (i > 0) + { + builder.Append(", "); + } + builder.Append(PrintClassTemplateParameter(classTemplate.Parameters[i], option)); + } + builder.Append('>'); + return builder.ToString(); + } + + public virtual string PrintClassTemplateSpecializationArgument(TemplateArgument templateArgument) + { + if (templateArgument.Kind == TemplateArgument.ArgumentKind.Integral) + { + return templateArgument.Integral.ToString(); + } + return templateArgument.Type.Type.Visit(new CppTypePrinter(Generator.Context)); + } + + public virtual string PrintClassTemplateSpecializationArguments(ClassTemplateSpecialization classTemplateSpecialization, bool includeEnclosingBrackets) + { + var builder = new StringBuilder(); + builder.Append('<'); + for (int i = 0; i < classTemplateSpecialization.Arguments.Count; i++) + { + if (i > 0) + { + builder.Append(", "); + } + builder.Append(PrintClassTemplateSpecializationArgument(classTemplateSpecialization.Arguments[i])); + } + builder.Append('>'); + return builder.ToString(); + } + + public virtual string GetQualifiedName(Declaration declaration, FQNOption option) + { + if (declaration is TranslationUnit) + { + return ""; + } + + var name = declaration.OriginalName; + var currentDeclaration = declaration; + + if (currentDeclaration is ClassTemplateSpecialization specialization) + { + if (!option.IgnoreTemplateParameters) + { + name = ($"{name}{PrintClassTemplateSpecializationArguments(specialization, true)}"); + } + } + else + { + if (currentDeclaration is not ClassTemplate template) + { + template = (ClassTemplate)Utils.FindDescribedTemplate(currentDeclaration); + } + if (template != null) + { + if (!option.IgnoreTemplateParameters) + { + name = ($"{name}{PrintClassTemplateParameters(template, true, TemplateParameterOption.AsArgument)}"); + } + } + } + + return name; + } + + public virtual string GetFullyQualifiedName(Declaration declaration, FQNOption option) + { + if (declaration is TranslationUnit) + { + return ""; + } + + var name = new StringBuilder(); + var currentDeclaration = declaration; + var needsTypename = false; + var depth = 0; + + while (true) + { + if (currentDeclaration == null || currentDeclaration is TranslationUnit) + { + break; + } + depth += 1; + var currentName = new StringBuilder(); + currentName.Append(currentDeclaration.OriginalName); + + if (currentDeclaration is ClassTemplateSpecialization specialization) + { + if (!option.IgnoreTemplateTemplateKeyword) + { + if (IsNestedTemplate(currentDeclaration)) + { + currentName.Insert(0, "template "); + } + } + if (!option.IgnoreTemplateParameters) + { + if (depth > 1) + { + needsTypename = true; + } + currentName.Append(PrintClassTemplateSpecializationArguments(specialization, true)); + } + } + else + { + if (currentDeclaration is not ClassTemplate template) + { + template = (ClassTemplate)Utils.FindDescribedTemplate(currentDeclaration); + } + if (template != null) + { + if (!option.IgnoreTemplateTemplateKeyword) + { + if (IsNestedTemplate(currentDeclaration)) + { + currentName.Insert(0, "template "); + } + } + if (!option.IgnoreTemplateParameters) + { + if (depth > 1) + { + needsTypename = true; + } + currentName.Append($"{name}{PrintClassTemplateParameters(template, true, TemplateParameterOption.AsArgument)}"); + } + } + } + + if (name.Length != 0) + { + name.Insert(0, "::"); + } + name.Insert(0, currentName); + currentDeclaration = currentDeclaration.OriginalNamespace; + } + if (!option.IgnoreGlobalNamespace) + { + name.Insert(0, "::"); + } + if (!option.IgnoreTemplateTypenameKeyword) + { + if (needsTypename) + { + name.Insert(0, "typename "); + } + } + + return name.ToString(); + } + + public virtual string GetContextualName(Declaration declaration, RegistrableGeneratorContext context, FQNOption option) + { + return GetCppContext(declaration, context, new FQNOption(false, true, false, false)) + "::" + GetQualifiedName(declaration, option); + } + + public virtual string GetRegistrationFunctionName(Declaration declaration, bool isRecusrive = false) + { + if (declaration is TranslationUnit translationUnit) + { + return isRecusrive ? "" : $"register_{translationUnit.FileNameWithoutExtension}"; + } + + var name = declaration.OriginalName; + var currentDeclaration = declaration; + while (true) + { + currentDeclaration = currentDeclaration.OriginalNamespace; + if (currentDeclaration == null || currentDeclaration is TranslationUnit) + { + break; + } + name = currentDeclaration.OriginalName + "_" + name; + } + return name; + } + + public virtual string GetRegistrationNameQuoted(Declaration declaration) + { + return $"\"{declaration.Name}\""; + } + + public virtual string GetBindingIdName(Declaration declaration) + { + return Generator.GeneratorOptions.BindingIdNamePredicate(GetRegistrationFunctionName(declaration)); + } + + public virtual string GetBindingIdValue(Declaration declaration, RegistrableGeneratorContext context) + { + return Generator.GeneratorOptions.BindingIdValuePredicate(GetContextualName(declaration, context, FQNOption.IgnoreNone)); + } + + public virtual string GetBindingName(Declaration declaration) + { + return Generator.GeneratorOptions.BindingNamePredicate(GetRegistrationFunctionName(declaration)); + } + + public virtual string GetRootContextName(RegistrableGeneratorContext context) + { + if (context != null) + { + var rootContextName = context.PeekRootContextName(); + if (rootContextName != null) + { + return rootContextName; + } + } + return "state"; + } + + public virtual string GetBindingContextNamespacePredicate(string state, string key) + { + return $"get_namespace({state}, \"{key}\")"; + } + + public virtual string GetBindingContext(Declaration declaration, RegistrableGeneratorContext context) + { + if (context != null) + { + var rootContextName = context.PeekRootContextName(); + if (rootContextName != null) + { + return rootContextName; + } + } + if (declaration.Namespace is TranslationUnit) + { + return GetRootContextName(context); + } + else + { + var name = GetRootContextName(context); + var currentDeclaration = declaration.Namespace; + var parentList = new List<Declaration>(); + while (true) + { + if (currentDeclaration != null || currentDeclaration is TranslationUnit) + { + break; + } + parentList.Insert(0, currentDeclaration); + currentDeclaration = currentDeclaration.Namespace; + } + foreach (var parent in parentList) + { + name = GetBindingContextNamespacePredicate(name, parent.Name); + } + return name; + } + } + + public string GetCppContext(Declaration entity, RegistrableGeneratorContext context, FQNOption option) + { + if (context != null) + { + var cppContext = context.PeekCppContext(); + if (cppContext != null) + { + return cppContext.GetFullQualifiedName(option); + } + } + return "";// GetFullyQualifiedName(entity.OriginalNamespace, option, context); + } + } +} diff --git a/src/Generator/Generators/Registrable/Utils/FQNOption.cs b/src/Generator/Generators/Registrable/Utils/FQNOption.cs new file mode 100644 index 000000000..026b0a93a --- /dev/null +++ b/src/Generator/Generators/Registrable/Utils/FQNOption.cs @@ -0,0 +1,44 @@ +namespace CppSharp.Generators.Registrable +{ + public class FQNOption + { + public static readonly FQNOption IgnoreNone = new(false, false, false, false); + public static readonly FQNOption IgnoreAll = new(true, true, true, true); + + public bool IgnoreGlobalNamespace { get; set; } + public bool IgnoreTemplateTypenameKeyword { get; set; } + public bool IgnoreTemplateTemplateKeyword { get; set; } + public bool IgnoreTemplateParameters { get; set; } + + public FQNOption(bool ignoreGlobalNamespace = false, + bool ignoreTemplateTypenameKeyword = false, + bool ignoreTemplateTemplateKeyword = false, + bool ignoreTemplateParameters = false) + { + IgnoreGlobalNamespace = ignoreGlobalNamespace; + IgnoreTemplateTypenameKeyword = ignoreTemplateTypenameKeyword; + IgnoreTemplateTemplateKeyword = ignoreTemplateTemplateKeyword; + IgnoreTemplateParameters = ignoreTemplateParameters; + } + + public static FQNOption operator |(FQNOption lhs, FQNOption rhs) + { + return new FQNOption( + lhs.IgnoreGlobalNamespace | rhs.IgnoreGlobalNamespace, + lhs.IgnoreTemplateTypenameKeyword | rhs.IgnoreTemplateTypenameKeyword, + lhs.IgnoreTemplateTemplateKeyword | rhs.IgnoreTemplateTemplateKeyword, + lhs.IgnoreTemplateParameters | rhs.IgnoreTemplateParameters + ); + } + + public static FQNOption operator &(FQNOption lhs, FQNOption rhs) + { + return new FQNOption( + lhs.IgnoreGlobalNamespace & rhs.IgnoreGlobalNamespace, + lhs.IgnoreTemplateTypenameKeyword & rhs.IgnoreTemplateTypenameKeyword, + lhs.IgnoreTemplateTemplateKeyword & rhs.IgnoreTemplateTemplateKeyword, + lhs.IgnoreTemplateParameters & rhs.IgnoreTemplateParameters + ); + } + } +} diff --git a/src/Generator/Generators/Registrable/Utils/InfoEntry.cs b/src/Generator/Generators/Registrable/Utils/InfoEntry.cs new file mode 100644 index 000000000..b2055b901 --- /dev/null +++ b/src/Generator/Generators/Registrable/Utils/InfoEntry.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace CppSharp.Generators.Registrable +{ + public class InfoEntry : IEquatable<InfoEntry> + { + public static readonly HashSet<InfoEntry> Registered = new(); + + public string Name { get; } + + public InfoEntry(string name) + { + if (Registered.Any(kind => kind.Name == name)) + { + throw new Exception($"InfoEntry has an already registered name: {Name}"); + } + Name = name; + Registered.Add(this); + } + + public static bool operator ==(InfoEntry obj1, InfoEntry obj2) + { + if (ReferenceEquals(obj1, obj2)) + { + return true; + } + if (obj1 is null) + { + return false; + } + if (obj2 is null) + { + return false; + } + return obj1.Equals(obj2); + } + + public static bool operator !=(InfoEntry obj1, InfoEntry obj2) => !(obj1 == obj2); + + public bool Equals(InfoEntry other) + { + if (other is null) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return Name.Equals(other.Name); + } + + public override bool Equals(object obj) => Equals(obj as InfoEntry); + + public override int GetHashCode() + { + unchecked + { + return Name.GetHashCode(); + } + } + } +} diff --git a/src/Generator/Generators/Registrable/Utils/InfoMap.cs b/src/Generator/Generators/Registrable/Utils/InfoMap.cs new file mode 100644 index 000000000..3017d00a1 --- /dev/null +++ b/src/Generator/Generators/Registrable/Utils/InfoMap.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace CppSharp.Generators.Registrable +{ + public class InfoMap<T> : Dictionary<InfoEntry, T> + { + public InfoMap() : base() + { + } + + public T1 Get<T1>(InfoEntry infoEntry) where T1 : T + { + return (T1)this[infoEntry]; + } + } +} diff --git a/src/Generator/Generators/Registrable/Utils/InfoMapStack.cs b/src/Generator/Generators/Registrable/Utils/InfoMapStack.cs new file mode 100644 index 000000000..2677386d7 --- /dev/null +++ b/src/Generator/Generators/Registrable/Utils/InfoMapStack.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace CppSharp.Generators.Registrable +{ + public class InfoMapStack<T> : InfoMap<Stack<T>> + { + public InfoMapStack() : base() + { + } + + public T1 Peek<T1>(InfoEntry infoEntry, T1 defaultValue = default) where T1 : T + { + if (TryGetValue(infoEntry, out Stack<T> stack)) + { + return (T1)stack.Peek(); + } + return defaultValue; + } + + public T1 Pop<T1>(InfoEntry infoEntry) where T1 : T + { + if (TryGetValue(infoEntry, out Stack<T> stack)) + { + return (T1)stack.Pop(); + } + throw new InvalidOperationException(); + } + + public void Push<T1>(InfoEntry infoEntry, T1 item) where T1 : T + { + if (!TryGetValue(infoEntry, out Stack<T> stack)) + { + this[infoEntry] = stack = new Stack<T>(); + } + stack.Push(item); + } + + public bool TryPeek<T1>(InfoEntry infoEntry, [MaybeNullWhen(false)] out T1 result) where T1 : T + { + if (TryGetValue(infoEntry, out Stack<T> stack)) + { + bool tempReturn = stack.TryPop(out T tempResult); + result = (T1)tempResult; + return tempReturn; + } + result = default; + return false; + } + + public bool TryPop<T1>(InfoEntry infoEntry, [MaybeNullWhen(false)] out T1 result) where T1 : T + { + if (TryGetValue(infoEntry, out Stack<T> stack)) + { + bool tempReturn = stack.TryPop(out T tempResult); + result = (T1)tempResult; + return tempReturn; + } + result = default; + return false; + } + + public void Scoped<T1>(InfoEntry infoEntry, T1 item, Action action) where T1 : T + { + Push(infoEntry, item); + action(); + Pop<T>(infoEntry); + } + } +} diff --git a/src/Generator/Generators/Registrable/Utils/TemplateParameterOption.cs b/src/Generator/Generators/Registrable/Utils/TemplateParameterOption.cs new file mode 100644 index 000000000..db32620e8 --- /dev/null +++ b/src/Generator/Generators/Registrable/Utils/TemplateParameterOption.cs @@ -0,0 +1,22 @@ +namespace CppSharp.Generators.Registrable +{ + public class TemplateParameterOption + { + public static readonly TemplateParameterOption AsParameter = new(false, false); + public static readonly TemplateParameterOption AsParameterNoDefault = new(false, true); + public static readonly TemplateParameterOption AsArgument = new(true, true); + + public bool IgnoreKeyword { get; set; } + public bool IgnoreDefault { get; set; } + public string CustomPrefix { get; set; } + + TemplateParameterOption(bool ignoreKeyword = false, + bool ignoreDefault = false, + string customPrefix = "") + { + IgnoreKeyword = ignoreKeyword; + IgnoreDefault = ignoreDefault; + CustomPrefix = customPrefix; + } + } +} diff --git a/src/Generator/Generators/Registrable/Utils/Utils.cs b/src/Generator/Generators/Registrable/Utils/Utils.cs new file mode 100644 index 000000000..cff813105 --- /dev/null +++ b/src/Generator/Generators/Registrable/Utils/Utils.cs @@ -0,0 +1,19 @@ +using CppSharp.AST; + +namespace CppSharp.Generators.Registrable +{ + public static class Utils + { + public static Declaration FindDescribedTemplate(Declaration declaration) + { + foreach (var template in declaration.Namespace.Templates) + { + if (template.TemplatedDecl == declaration) + { + return template; + } + } + return null; + } + } +} From c86106abaf742f0127504067dd362c659d13f971 Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Thu, 14 Dec 2023 10:51:19 +0200 Subject: [PATCH 02/13] Registrable: add support for field/variable --- .../Registrable/Lua/Sol/LuaSolSources.cs | 247 +++++++++++++++++- .../Registrable/RegistrableNamingStrategy.cs | 2 +- .../Registrable/Utils/InfoMapStack.cs | 7 +- .../Generators/Registrable/Utils/Utils.cs | 5 + 4 files changed, 248 insertions(+), 13 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index 410e3f417..24e88cafa 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -1,4 +1,5 @@ using CppSharp.AST; +using CppSharp.Generators.C; using System.Collections.Generic; using System.Linq; using System.Text; @@ -103,6 +104,14 @@ public virtual void GenerateTranslationUnitRegistrationFunctionBegin(Translation public virtual void GenerateTranslationUnitRegistrationFunctionBody(TranslationUnit translationUnit) { GenerateDeclarationContainerList(translationUnit); + + GenerationContext.Scoped(RegistrableGeneratorContext.IsDetach, DetachmentOption.On, () => + { + foreach (var variable in translationUnit.Variables) + { + variable.Visit(this); + } + }); } public virtual void GenerateTranslationUnitRegistrationFunctionEnd(TranslationUnit translationUnit) @@ -175,19 +184,14 @@ public virtual void GenerateNamespaceBody(Namespace @namespace) public virtual void GenerateNamespaceDeclarationList(Namespace @namespace, DetachmentOption detachment) { - if (detachment == DetachmentOption.Off) - { - GenerateNamespaceFunctions(@namespace); - GenerateNamespaceVariables(@namespace); - } - else + GenerateNamespaceContainerList(@namespace); + GenerateNamespaceTemplates(@namespace); + GenerateNamespaceTypedefs(@namespace); + GenerationContext.Scoped(RegistrableGeneratorContext.IsDetach, DetachmentOption.On, () => { - GenerateNamespaceContainerList(@namespace); - GenerateNamespaceTemplates(@namespace); - GenerateNamespaceTypedefs(@namespace); GenerateNamespaceFunctions(@namespace); GenerateNamespaceVariables(@namespace); - } + }); } public virtual void GenerateNamespaceContainerList(Namespace @namespace) @@ -209,6 +213,10 @@ public virtual void GenerateNamespaceFunctions(Namespace @namespace) public virtual void GenerateNamespaceVariables(Namespace @namespace) { + foreach (var variable in @namespace.Variables) + { + variable.Visit(this); + } } public virtual void GenerateNamespaceEnd(Namespace @namespace) @@ -543,6 +551,14 @@ public virtual void GenerateClassDeclFunctions(Class @class) public virtual void GenerateClassDeclVariables(Class @class) { + foreach (var field in @class.Fields) + { + field.Visit(this); + } + foreach (var variable in @class.Variables) + { + variable.Visit(this); + } } public virtual void GenerateClassDeclEnd(Class @class) @@ -611,6 +627,217 @@ public override bool VisitClassDecl(Class @class) #endregion + #region Field + + #region Field + + public virtual bool CanGenerateFieldDecl(Field field) + { + if (AlreadyVisited(field)) + { + return false; + } + else if (field.Access != AccessSpecifier.Public) + { + return false; + } + else if (!NonTemplateAllowed) + { + return false; + } + return field.IsGenerated; + } + + public virtual bool GenerateFieldDecl(Field field) + { + var isDetach = GenerationContext.PeekIsDetach(DetachmentOption.Off); + + if (isDetach == DetachmentOption.Forced || isDetach == Utils.FindDetachmentOption(field)) + { + string fieldName = field.Name; + string fieldNameQuoted = $"\"{fieldName}\""; + string fieldContextualName = NamingStrategy.GetContextualName(field, GenerationContext, FQNOption.IgnoreNone); + + if (isDetach != DetachmentOption.Off) + { + Write($"{NamingStrategy.GetBindingContext(field, GenerationContext)}[{fieldNameQuoted}] = "); + } + else + { + WriteLine(","); + Write($"{fieldNameQuoted}, "); + } + // TODO : check for typemaps!!! + { + Write($"&{fieldContextualName}"); + } + if (isDetach != DetachmentOption.Off) + { + WriteLine(";"); + } + } + + return true; + } + + #endregion + + #region Bitfield + + public virtual bool CanGenerateFieldDeclBitfield(Field field) + { + if (AlreadyVisited(field)) + { + return false; + } + else if (field.Access != AccessSpecifier.Public) + { + return false; + } + else if (!NonTemplateAllowed) + { + return false; + } + return field.IsGenerated; + } + + public virtual bool GenerateFieldDeclBitfield(Field field) + { + var isDetach = GenerationContext.PeekIsDetach(DetachmentOption.Off); + + if (isDetach == DetachmentOption.Forced || isDetach == Utils.FindDetachmentOption(field)) + { + string bitfieldOriginalName = field.OriginalName; + string bitfieldName = field.Name; + string bitfieldNameQuoted = $"\"{bitfieldName}\""; + string bitfieldCppContext = NamingStrategy.GetCppContext(field, GenerationContext, FQNOption.IgnoreNone); + string bitfieldType = field.Type.Visit(new CppTypePrinter(Context)); + + if (isDetach != DetachmentOption.Off) + { + Write($"{NamingStrategy.GetBindingContext(field, GenerationContext)}[{bitfieldNameQuoted}] = "); + } + else + { + WriteLine(","); + Write($"{bitfieldNameQuoted}, "); + } + WriteLine("::sol::property("); + Indent(); + WriteLine($"[]({bitfieldCppContext}& self) {{"); + Indent(); + WriteLine($"return self.{bitfieldOriginalName};"); + Unindent(); + WriteLine("}, "); + WriteLine($"[]({bitfieldCppContext}& self, {bitfieldType} value) {{"); + Indent(); + WriteLine($"self.{bitfieldOriginalName} = value;"); + Unindent(); + WriteLine("}"); + Unindent(); + Write(")"); + if (isDetach != DetachmentOption.Off) + { + WriteLine(";"); + } + } + + return true; + } + + #endregion + + public override bool VisitFieldDecl(Field field) + { + if (field.IsBitField) + { + if (!CanGenerateFieldDeclBitfield(field)) + { + return false; + } + + return GenerateFieldDeclBitfield(field); + } + else + { + if (!CanGenerateFieldDecl(field)) + { + return false; + } + + return GenerateFieldDecl(field); + } + return false; + } + + #endregion + + #region Variable + + public virtual bool CanGenerateVariableDecl(Variable variable) + { + if (AlreadyVisited(variable)) + { + return false; + } + else if (variable.Access != AccessSpecifier.Public) + { + return false; + } + else if (!NonTemplateAllowed) + { + return false; + } + return variable.IsGenerated; + } + + public virtual bool GenerateVariableDecl(Variable variable) + { + var isDetach = GenerationContext.PeekIsDetach(DetachmentOption.Off); + + if (isDetach == DetachmentOption.Forced || isDetach == Utils.FindDetachmentOption(variable)) + { + string variableName = variable.Name; + string variableNameQuoted = $"\"{variableName}\""; + string variableBindingContext = NamingStrategy.GetBindingContext(variable, GenerationContext); + string variableContextualName = NamingStrategy.GetContextualName(variable, GenerationContext, FQNOption.IgnoreNone); + // TODO: Bug in sol until it gets resolved: we can only bind static class variable by reference. + if (variable.OriginalNamespace is Class) + { + variableContextualName = $"::std::ref({variableContextualName})"; + } + + // TODO: check for typemaps!!! + if (isDetach != DetachmentOption.Off) + { + Write($"{variableBindingContext}[{variableNameQuoted}] = ::sol::var({variableContextualName});"); + } + else + { + WriteLine(","); + Write($"{variableNameQuoted}, ::sol::var({variableContextualName})"); + } + if (isDetach != DetachmentOption.Off) + { + WriteLine(";"); + } + } + + return true; + } + + public override bool VisitVariableDecl(Variable variable) + { + if (!CanGenerateVariableDecl(variable)) + { + return false; + } + + return GenerateVariableDecl(variable); + } + + #endregion + public virtual bool CanGenerateConstructor(Method method) { // if not self:isNonTemplateAllowed(context) then diff --git a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs index 9d8bb7f72..fe7a4537e 100644 --- a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs +++ b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs @@ -396,7 +396,7 @@ public string GetCppContext(Declaration entity, RegistrableGeneratorContext cont return cppContext.GetFullQualifiedName(option); } } - return "";// GetFullyQualifiedName(entity.OriginalNamespace, option, context); + return GetFullyQualifiedName(entity.OriginalNamespace, option); } } } diff --git a/src/Generator/Generators/Registrable/Utils/InfoMapStack.cs b/src/Generator/Generators/Registrable/Utils/InfoMapStack.cs index 2677386d7..2fec16530 100644 --- a/src/Generator/Generators/Registrable/Utils/InfoMapStack.cs +++ b/src/Generator/Generators/Registrable/Utils/InfoMapStack.cs @@ -14,7 +14,10 @@ public T1 Peek<T1>(InfoEntry infoEntry, T1 defaultValue = default) where T1 : T { if (TryGetValue(infoEntry, out Stack<T> stack)) { - return (T1)stack.Peek(); + if (stack.Count > 0) + { + return (T1)stack.Peek(); + } } return defaultValue; } @@ -61,7 +64,7 @@ public bool TryPop<T1>(InfoEntry infoEntry, [MaybeNullWhen(false)] out T1 result return false; } - public void Scoped<T1>(InfoEntry infoEntry, T1 item, Action action) where T1 : T + public void Scoped(InfoEntry infoEntry, T item, Action action) { Push(infoEntry, item); action(); diff --git a/src/Generator/Generators/Registrable/Utils/Utils.cs b/src/Generator/Generators/Registrable/Utils/Utils.cs index cff813105..ef03bbb5c 100644 --- a/src/Generator/Generators/Registrable/Utils/Utils.cs +++ b/src/Generator/Generators/Registrable/Utils/Utils.cs @@ -15,5 +15,10 @@ public static Declaration FindDescribedTemplate(Declaration declaration) } return null; } + + public static DetachmentOption FindDetachmentOption(Declaration declaration) + { + return (declaration.Namespace is Class) ? DetachmentOption.Off : DetachmentOption.On; + } } } From b653daf297310f36d2eb3a54b8b29347bbe300dc Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Thu, 14 Dec 2023 11:06:51 +0200 Subject: [PATCH 03/13] Registrable: fix duplicated semi colon --- .../Generators/Registrable/Lua/Sol/LuaSolSources.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index 24e88cafa..db569922e 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -810,17 +810,13 @@ public virtual bool GenerateVariableDecl(Variable variable) // TODO: check for typemaps!!! if (isDetach != DetachmentOption.Off) { - Write($"{variableBindingContext}[{variableNameQuoted}] = ::sol::var({variableContextualName});"); + WriteLine($"{variableBindingContext}[{variableNameQuoted}] = ::sol::var({variableContextualName});"); } else { WriteLine(","); Write($"{variableNameQuoted}, ::sol::var({variableContextualName})"); } - if (isDetach != DetachmentOption.Off) - { - WriteLine(";"); - } } return true; From 736531bd0b9781a856a0ee53156b1ad73313896c Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Thu, 14 Dec 2023 12:41:33 +0200 Subject: [PATCH 04/13] Registrable: add support for constructor --- .../Registrable/Lua/Sol/LuaSolSources.cs | 115 ++++++++++++++++-- 1 file changed, 106 insertions(+), 9 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index db569922e..6a907b519 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -519,6 +519,7 @@ public virtual void GenerateClassDeclDeclarationList(Class @class, DetachmentOpt { if (detachment == DetachmentOption.Off) { + GenerateConstructors(@class, @class.Constructors); GenerateClassDeclFunctions(@class); GenerateClassDeclVariables(@class); } @@ -834,11 +835,79 @@ public override bool VisitVariableDecl(Variable variable) #endregion + #region Constructor + + public virtual bool NeedExpansionForConstructors(Class @class, IEnumerable<Method> constructors) + { + return false; + } + + public virtual void GenerateConstructors(Class @class, IEnumerable<Method> constructors) + { + var isDetach = GenerationContext.PeekIsDetach(); + + List<Method> filteredConstructors = constructors.Where((method) => CanGenerateConstructor(method)).ToList(); + if (filteredConstructors.Any()) + { + Method constructor = filteredConstructors.First(); + string constructorBindingContext = NamingStrategy.GetBindingContext(constructor, GenerationContext); + string constructorContextualName = NamingStrategy.GetContextualName(constructor, GenerationContext, FQNOption.IgnoreNone); + + if (isDetach == DetachmentOption.Forced || isDetach == Utils.FindDetachmentOption(constructor)) + { + + if (isDetach != DetachmentOption.Off) + { + Write($"{constructorBindingContext}[\"new\"] = "); + } + else + { + WriteLine(","); + Write($"\"new\", "); + } + if (NeedExpansionForConstructors(@class, constructors)) + { + Write("::sol::factories("); + Indent(); + for (int i = 0; i < filteredConstructors.Count; i++) + { + if (i > 0) + { + Write(","); + } + NewLine(); + GenerateConstructor(@class, filteredConstructors[i], true); + } + Unindent(); + WriteLine(")"); + } + else + { + Write("::sol::constructors<"); + Indent(); + for (int i = 0; i < filteredConstructors.Count; i++) + { + if (i > 0) + { + Write(","); + } + NewLine(); + GenerateConstructor(@class, filteredConstructors[i], false); + } + Unindent(); + NewLine(); + Write(">()"); + } + if (isDetach != DetachmentOption.Off) + { + WriteLine(";"); + } + } + } + } + public virtual bool CanGenerateConstructor(Method method) { - // if not self:isNonTemplateAllowed(context) then - // return true - // end if (AlreadyVisited(method)) { return false; @@ -847,20 +916,48 @@ public virtual bool CanGenerateConstructor(Method method) { return false; } + else if (!NonTemplateAllowed) + { + return false; + } return method.IsGenerated; } - public virtual void GenerateConstructors(Class @class, IEnumerable<Method> constructors) + public virtual void GenerateConstructor(Class @class, Method constructor, bool doExpand) { - var isDetach = GenerationContext.PeekIsDetach(); - - if (isDetach == DetachmentOption.Forced) + if (doExpand) { - var filteredConstructors = constructors.Where((method) => CanGenerateConstructor(method)); - foreach (var constructor in constructors) + // TODO: Implement when ready + } + else + { + Write(NamingStrategy.GetCppContext(constructor, GenerationContext, FQNOption.IgnoreNone)); + Write("("); + var needsComma = false; + foreach (var parameter in constructor.Parameters) + { + if (needsComma) + { + Write(", "); + } + else + { + needsComma = true; + } + Write(parameter.Type.Visit(new CppTypePrinter(Context))); + } + if (constructor.IsVariadic) { + if (needsComma) + { + Write(", "); + } + Write("..."); } + Write(")"); } } + + #endregion } } From d87d95a0cf0796bd4f321e94bdc606978dedd3c4 Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Thu, 14 Dec 2023 13:46:36 +0200 Subject: [PATCH 05/13] Registrable: add support for method --- .../Registrable/Lua/Sol/LuaSolSources.cs | 130 +++++++++++++++++- 1 file changed, 126 insertions(+), 4 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index 6a907b519..799adade2 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -520,6 +520,12 @@ public virtual void GenerateClassDeclDeclarationList(Class @class, DetachmentOpt if (detachment == DetachmentOption.Off) { GenerateConstructors(@class, @class.Constructors); + + var methods = @class.Methods.Where(method => !(method.IsConstructor || method.IsDestructor || method.IsOperator)); + var uniqueMethods = methods.GroupBy(m => m.Name); + foreach (var group in uniqueMethods) + GenerateMethods(@class, group.ToList()); + GenerateClassDeclFunctions(@class); GenerateClassDeclVariables(@class); } @@ -906,13 +912,13 @@ public virtual void GenerateConstructors(Class @class, IEnumerable<Method> const } } - public virtual bool CanGenerateConstructor(Method method) + public virtual bool CanGenerateConstructor(Method constructor) { - if (AlreadyVisited(method)) + if (AlreadyVisited(constructor)) { return false; } - else if (method.Access != AccessSpecifier.Public) + else if (constructor.Access != AccessSpecifier.Public) { return false; } @@ -920,7 +926,7 @@ public virtual bool CanGenerateConstructor(Method method) { return false; } - return method.IsGenerated; + return constructor.IsGenerated; } public virtual void GenerateConstructor(Class @class, Method constructor, bool doExpand) @@ -959,5 +965,121 @@ public virtual void GenerateConstructor(Class @class, Method constructor, bool d } #endregion + + #region Method + + public virtual bool NeedExpansionForMethods(Class @class, IEnumerable<Method> methods) + { + return false; + } + + public virtual void GenerateMethods(Class @class, IEnumerable<Method> methods) + { + var isDetach = GenerationContext.PeekIsDetach(); + + List<Method> filteredMethods = methods.Where((method) => CanGenerateMethod(method)).ToList(); + if (filteredMethods.Any()) + { + Method method = filteredMethods.First(); + string methodName = method.Name; + string methodNameQuoted = $"\"{methodName}\""; + string methodBindingContext = NamingStrategy.GetBindingContext(method, GenerationContext); + string methodContextualName = NamingStrategy.GetContextualName(method, GenerationContext, FQNOption.IgnoreNone); + + if (isDetach == DetachmentOption.Forced || isDetach == Utils.FindDetachmentOption(method)) + { + + if (isDetach != DetachmentOption.Off) + { + Write($"{methodBindingContext}[{methodNameQuoted}] = "); + } + else + { + WriteLine(","); + Write($"{methodNameQuoted}, "); + } + if (filteredMethods.Count == 1) + { + GenerateMethod(@class, filteredMethods.First()); + } + else + { + Write("::sol::overload("); + Indent(); + for (int i = 0; i < filteredMethods.Count; i++) + { + if (i > 0) + { + Write(","); + } + NewLine(); + GenerateMethod(@class, filteredMethods[i]); + } + Unindent(); + NewLine(); + Write(")"); + } + if (isDetach != DetachmentOption.Off) + { + WriteLine(";"); + } + } + } + } + + public virtual bool CanGenerateMethod(Method method) + { + if (AlreadyVisited(method)) + { + return false; + } + else if (method.Access != AccessSpecifier.Public) + { + return false; + } + else if (!NonTemplateAllowed) + { + return false; + } + return method.IsGenerated; + } + + public virtual void GenerateMethod(Class @class, Method method) + { + { + Write("static_cast<"); + Write(method.ReturnType.Visit(new CppTypePrinter(Context))); + Write("("); + Write("*)"); + Write("("); + var needsComma = false; + foreach (var parameter in method.Parameters) + { + if (needsComma) + { + Write(", "); + } + else + { + needsComma = true; + } + Write(parameter.Type.Visit(new CppTypePrinter(Context))); + } + if (method.IsVariadic) + { + if (needsComma) + { + Write(", "); + } + Write("..."); + } + Write(")"); + Write(">(&"); + Write(NamingStrategy.GetContextualName(method, GenerationContext, FQNOption.IgnoreNone)); + Write(")"); + } + } + + #endregion } } From 94da6bee97352a66cc0c69ed6b168db7b0a4016b Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Thu, 14 Dec 2023 14:09:53 +0200 Subject: [PATCH 06/13] Registrable: add support for function --- .../Registrable/Lua/Sol/LuaSolSources.cs | 138 +++++++++++++++++- 1 file changed, 135 insertions(+), 3 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index 799adade2..ff86ffa53 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -111,6 +111,13 @@ public virtual void GenerateTranslationUnitRegistrationFunctionBody(TranslationU { variable.Visit(this); } + + var methods = translationUnit.Functions.Where(method => !(method.IsOperator)); + var overloads = methods.GroupBy(m => m.Name); + foreach (var overload in overloads) + { + GenerateFunctions(translationUnit, overload.ToList()); + } }); } @@ -191,6 +198,13 @@ public virtual void GenerateNamespaceDeclarationList(Namespace @namespace, Detac { GenerateNamespaceFunctions(@namespace); GenerateNamespaceVariables(@namespace); + + var methods = @namespace.Functions.Where(method => !(method.IsOperator)); + var overloads = methods.GroupBy(m => m.Name); + foreach (var overload in overloads) + { + GenerateFunctions(@namespace, overload.ToList()); + } }); } @@ -522,9 +536,11 @@ public virtual void GenerateClassDeclDeclarationList(Class @class, DetachmentOpt GenerateConstructors(@class, @class.Constructors); var methods = @class.Methods.Where(method => !(method.IsConstructor || method.IsDestructor || method.IsOperator)); - var uniqueMethods = methods.GroupBy(m => m.Name); - foreach (var group in uniqueMethods) - GenerateMethods(@class, group.ToList()); + var overloads = methods.GroupBy(m => m.Name); + foreach (var overload in overloads) + { + GenerateMethods(@class, overload.ToList()); + } GenerateClassDeclFunctions(@class); GenerateClassDeclVariables(@class); @@ -966,6 +982,122 @@ public virtual void GenerateConstructor(Class @class, Method constructor, bool d #endregion + #region Function + + public virtual bool NeedExpansionForFunctions(Declaration declaration, IEnumerable<Function> functions) + { + return false; + } + + public virtual void GenerateFunctions(Declaration declaration, IEnumerable<Function> functions) + { + var isDetach = GenerationContext.PeekIsDetach(); + + List<Function> filteredFunctions = functions.Where((function) => CanGenerateFunction(function)).ToList(); + if (filteredFunctions.Any()) + { + Function function = filteredFunctions.First(); + string functionName = function.Name; + string functionNameQuoted = $"\"{functionName}\""; + string functionBindingContext = NamingStrategy.GetBindingContext(function, GenerationContext); + string functionContextualName = NamingStrategy.GetContextualName(function, GenerationContext, FQNOption.IgnoreNone); + + if (isDetach == DetachmentOption.Forced || isDetach == Utils.FindDetachmentOption(function)) + { + + if (isDetach != DetachmentOption.Off) + { + Write($"{functionBindingContext}[{functionNameQuoted}] = "); + } + else + { + WriteLine(","); + Write($"{functionNameQuoted}, "); + } + if (filteredFunctions.Count == 1) + { + GenerateFunction(declaration, filteredFunctions.First()); + } + else + { + Write("::sol::overload("); + Indent(); + for (int i = 0; i < filteredFunctions.Count; i++) + { + if (i > 0) + { + Write(","); + } + NewLine(); + GenerateFunction(declaration, filteredFunctions[i]); + } + Unindent(); + NewLine(); + Write(")"); + } + if (isDetach != DetachmentOption.Off) + { + WriteLine(";"); + } + } + } + } + + public virtual bool CanGenerateFunction(Function function) + { + if (AlreadyVisited(function)) + { + return false; + } + else if (function.Access != AccessSpecifier.Public) + { + return false; + } + else if (!NonTemplateAllowed) + { + return false; + } + return function.IsGenerated; + } + + public virtual void GenerateFunction(Declaration declaration, Function function) + { + { + Write("static_cast<"); + Write(function.ReturnType.Visit(new CppTypePrinter(Context))); + Write("("); + Write("*)"); + Write("("); + var needsComma = false; + foreach (var parameter in function.Parameters) + { + if (needsComma) + { + Write(", "); + } + else + { + needsComma = true; + } + Write(parameter.Type.Visit(new CppTypePrinter(Context))); + } + if (function.IsVariadic) + { + if (needsComma) + { + Write(", "); + } + Write("..."); + } + Write(")"); + Write(">(&"); + Write(NamingStrategy.GetContextualName(function, GenerationContext, FQNOption.IgnoreNone)); + Write(")"); + } + } + + #endregion + #region Method public virtual bool NeedExpansionForMethods(Class @class, IEnumerable<Method> methods) From 97110fd21fce5f5ccf700dfbfeb29daf94983547 Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Thu, 14 Dec 2023 14:58:22 +0200 Subject: [PATCH 07/13] Registrable: fix lua artifacts --- .../Registrable/Lua/Sol/LuaSolSources.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index ff86ffa53..661905db6 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -261,9 +261,6 @@ public virtual void GenerateNamespace(Namespace @namespace) public virtual bool CanGenerateNamespace(Namespace @namespace) { - // if not self:isNonTemplateAllowed(context) then - // return true - // end if (AlreadyVisited(@namespace)) { return false; @@ -272,6 +269,10 @@ public virtual bool CanGenerateNamespace(Namespace @namespace) { return false; } + else if (!NonTemplateAllowed) + { + return false; + } return @namespace.IsGenerated; } @@ -466,9 +467,6 @@ public virtual void GenerateEnumDecl(Enumeration enumeration) public virtual bool CanGenerateEnumDecl(Enumeration enumeration) { - // if not self:isNonTemplateAllowed(context) then - // return true - // end if (AlreadyVisited(enumeration)) { return false; @@ -477,6 +475,10 @@ public virtual bool CanGenerateEnumDecl(Enumeration enumeration) { return false; } + else if (!NonTemplateAllowed) + { + return false; + } return enumeration.IsGenerated; } From 9fb03a0a07b489d366ba829fd6981899b96eb24f Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Thu, 14 Dec 2023 18:37:13 +0200 Subject: [PATCH 08/13] Registrable: cleanup + improvements --- .../Registrable/Lua/Sol/LuaSolGenerator.cs | 1 - .../Lua/Sol/LuaSolGeneratorOptions.cs | 12 +++ .../Registrable/Lua/Sol/LuaSolHeaders.cs | 87 ++-------------- .../Registrable/Lua/Sol/LuaSolSources.cs | 73 +++++++++++++- .../RegistrableGeneratorOptions.cs | 98 +++++++++++++------ .../Registrable/RegistrableNamingStrategy.cs | 24 ++--- 6 files changed, 171 insertions(+), 124 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs index db7766ad0..596a4c4b1 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs @@ -3,7 +3,6 @@ namespace CppSharp.Generators.Registrable.Lua.Sol { - public class LuaSolGenerator : Generator { public const string Id = "Lua::Sol"; diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs index 158cb47bb..bf5169eb3 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs @@ -8,5 +8,17 @@ public LuaSolGeneratorOptions(LuaSolGenerator generator) : base() { NamingStrategy = new LuaSolNamingStrategy(generator); } + + public override string DefaultRootContextType => "::sol::state_view&"; + + public override string DefaultRootContextName => "state"; + + public override string DefaultTemplateContextDefaultType => "::sol::table"; + + public override string DefaultTemplateContextDefaultValue => "::sol::nil"; + + public override string DefaultCmakeVariableHeader => "LUA_SOL_BINDINGS_HEADER"; + + public override string DefaultCmakeVariableSource => "LUA_SOL_BINDINGS_SOURCE"; } } diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs index 78599525f..971a6fd51 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs @@ -12,6 +12,8 @@ public LuaSolHeaders(LuaSolGenerator generator, IEnumerable<TranslationUnit> uni public override string FileExtension => "h"; + protected override bool TemplateAllowed { get { return true; } } + public override void Process() { GenerateFilePreamble(CommentKind.BCPL); @@ -20,32 +22,18 @@ public override void Process() WriteLine("#pragma once"); PopBlock(NewLineKind.BeforeNextBlock); - //NewLine(); - //PushBlock(BlockKind.Includes); - //GenerateIncludes(); - //PopBlock(NewLineKind.BeforeNextBlock); - TranslationUnit.Visit(this); - - //PushBlock(BlockKind.Footer); - //PopBlock(); - - //PushBlock(BlockKind.Class); - //PopBlock(NewLineKind.IfNotEmpty); - - //RegistrableGeneratorContext mycontext = new RegistrableGeneratorContext(); - //string a = (string)mycontext[new InfoEntry("")].Pop(); } #region TranslationUnit - public virtual void GenerateTranslationUnitNamespaceBegin(TranslationUnit translationUnit) + public override void GenerateTranslationUnitNamespaceBegin(TranslationUnit translationUnit) { PushBlock(BlockKind.Namespace); WriteLine($"namespace {TranslationUnit.Module.OutputNamespace} {{"); } - public virtual void GenerateTranslationUnitNamespaceEnd(TranslationUnit translationUnit) + public override void GenerateTranslationUnitNamespaceEnd(TranslationUnit translationUnit) { WriteLine($"}} // namespace {TranslationUnit.Module.OutputNamespace}"); PopBlock(); @@ -58,14 +46,14 @@ public virtual void GenerateTranslationUnitRegistrationFunctionDeclaration(Trans NewLine(); } - public virtual void GenerateTranslationUnit(TranslationUnit translationUnit) + public override void GenerateTranslationUnit(TranslationUnit translationUnit) { GenerateTranslationUnitNamespaceBegin(translationUnit); GenerateTranslationUnitRegistrationFunctionDeclaration(translationUnit); GenerateTranslationUnitNamespaceEnd(translationUnit); } - public virtual bool CanGenerateTranslationUnit(TranslationUnit unit) + public override bool CanGenerateTranslationUnit(TranslationUnit unit) { if (AlreadyVisited(unit)) { @@ -88,8 +76,6 @@ public override bool VisitTranslationUnit(TranslationUnit unit) #endregion - // - public virtual void GenerateMain() { VisitNamespace(TranslationUnit); @@ -97,67 +83,10 @@ public virtual void GenerateMain() public virtual void GenerateIncludes() { - foreach (var include in Generator.GeneratorOptions.CommonIncludes) - { - WriteLineIndent(include.ToString()); - } - } - - //public override bool VisitNamespace(Namespace @namespace) - //{ - // base.VisitNamespace(@namespace); - // return true; - //} - - public override bool VisitMethodDecl(Method method) - { - return true; - } - - public override bool VisitFunctionDecl(Function function) - { - //if (FunctionIsTemplate(function)) - //{ - // Console.WriteLine("test"); - //} - return true; - } - - public override bool VisitClassTemplateDecl(ClassTemplate template) - { - return true; - } - - public override bool VisitVariableDecl(Variable variable) - { - return true; - } - - public override bool VisitTypeAliasTemplateDecl(TypeAliasTemplate typeAliasTemplate) - { - return true; - } - - public override bool VisitTypedefNameDecl(TypedefNameDecl typedef) - { - return true; - } - - public override bool VisitFunctionTemplateDecl(FunctionTemplate template) - { - return true; - } - - public static bool FunctionIsTemplate(Function function) - { - foreach (var template in function.Namespace.Templates) + if (Generator.GeneratorOptions.BaseInclude != null) { - if (template.TemplatedDecl == function) - { - return true; - } + WriteLineIndent(Generator.GeneratorOptions.BaseInclude.ToString()); } - return false; } } } diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index 661905db6..03f965e7e 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -118,6 +118,11 @@ public virtual void GenerateTranslationUnitRegistrationFunctionBody(TranslationU { GenerateFunctions(translationUnit, overload.ToList()); } + + foreach (var typedef in translationUnit.Typedefs) + { + typedef.Visit(this); + } }); } @@ -205,6 +210,11 @@ public virtual void GenerateNamespaceDeclarationList(Namespace @namespace, Detac { GenerateFunctions(@namespace, overload.ToList()); } + + foreach (var typedef in @namespace.Typedefs) + { + typedef.Visit(this); + } }); } @@ -235,7 +245,7 @@ public virtual void GenerateNamespaceVariables(Namespace @namespace) public virtual void GenerateNamespaceEnd(Namespace @namespace) { - GenerateNamespaceDeclarationList(@namespace, DetachmentOption.On); + //GenerateNamespaceDeclarationList(@namespace, DetachmentOption.On); } public virtual void GenerateNamespaceGlobalStateRegistration(Namespace @namespace) @@ -1215,5 +1225,66 @@ public virtual void GenerateMethod(Class @class, Method method) } #endregion + + #region Typedef + + public virtual bool CanGenerateTypedefNameDecl(TypedefNameDecl typedef) + { + if (AlreadyVisited(typedef)) + { + return false; + } + else if (typedef.Access != AccessSpecifier.Public) + { + return false; + } + else if (!NonTemplateAllowed) + { + return false; + } + return typedef.IsGenerated; + } + + public virtual void GenerateTypedefNameDecl(TypedefNameDecl typedef) + { + var type = typedef.Type; + if (type is TemplateSpecializationType templateSpecializationType) + { + string typedefName = typedef.Name; + string typedefNameQuoted = $"\"{typedefName}\""; + string typedefRegistrationFunctionName = NamingStrategy.GetFullyQualifiedName(templateSpecializationType.GetClassTemplateSpecialization(), new FQNOption() + { + IgnoreTemplateTypenameKeyword = true + }); + string typedefBindingContext = NamingStrategy.GetBindingContext(typedef, GenerationContext); + string typedefRootContextName = NamingStrategy.GetRootContextName(GenerationContext); + + WriteLine($"global{typedefRegistrationFunctionName}{{}}({typedefRootContextName}, {typedefBindingContext}, {typedefNameQuoted}); /* directly */"); + } + } + + public override bool VisitTypedefNameDecl(TypedefNameDecl typedef) + { + if (!CanGenerateTypedefNameDecl(typedef)) + { + return false; + } + + GenerateTypedefNameDecl(typedef); + + return true; + } + + public override bool VisitTypedefDecl(TypedefDecl typedef) + { + return VisitTypedefNameDecl(typedef); + } + + public override bool VisitTypeAliasDecl(TypeAlias typeAlias) + { + return VisitTypedefNameDecl(typeAlias); + } + + #endregion } } diff --git a/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs index 7e7e82d13..83650e65d 100644 --- a/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs +++ b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs @@ -1,50 +1,86 @@ using CppSharp.Generators.C; -using System.Collections.Generic; namespace CppSharp.Generators.Registrable { + public enum ImportedClassTemplateMode + { + Direct, + Indirect, + Import + } + public abstract class RegistrableGeneratorOptions { public delegate string Delegate(string name); protected Generator generator; - public virtual ISet<CInclude> CommonIncludes { get; } public virtual string OutputSubDir { get; } + public virtual string RootContextType { get; } + public virtual string RootContextName { get; } + public virtual string RegisterFunctionName { get; } + public virtual CInclude? BaseInclude { get; } public Delegate BindingIdNamePredicate { get; } public Delegate BindingIdValuePredicate { get; } public Delegate BindingNamePredicate { get; } + public string TemplateTypenameState { get; } + public string TemplateTypenameContext { get; } + public string TemplateIdentifierState { get; } + public string TemplateIdentifierContext { get; } + public string TemplateContextDefaultType { get; } + public string TemplateContextDefaultValue { get; } + public ImportedClassTemplateMode ImportedTemplateMode { get; } + public string CppValidatorFileName { get; } + public string CmakeVariableHeader { get; } + public string CmakeVariableSource { get; } + public string EqualityFunctionTemplateFullyQualifiedName { get; } + public string StaticCastFunctionTemplateFullyQualifiedName { get; } + public string DynamicCastFunctionTemplateFullyQualifiedName { get; } - public RegistrableGeneratorOptions() - { - CommonIncludes = new HashSet<CInclude>(); - OutputSubDir = null; - BindingIdNamePredicate = DefaultBindingIdNamePredicate(); - BindingIdValuePredicate = DefaultBindingIdValuePredicate(); - BindingNamePredicate = DefaultBindingNamePredicate(); - } + public virtual string DefaultOutputSubdir => ""; + public abstract string DefaultRootContextType { get; } + public abstract string DefaultRootContextName { get; } + public virtual string DefaultRegisterFunctionName => "register_"; + public virtual CInclude? DefaultBaseInclude => null; + public virtual Delegate DefaultBindingIdNamePredicate => (string name) => $"_cppbind_id_{name}"; + public virtual Delegate DefaultBindingIdValuePredicate => (string name) => $"typeid({name}).name()"; + public virtual Delegate DefaultBindingNamePredicate => (string name) => $"_cppbind_{name}"; + public virtual string DefaultTemplateTypenameState => "CppBindState"; + public virtual string DefaultTemplateTypenameContext => "CppBindContext"; + public virtual string DefaultTemplateIdentifierState => "cpp_bind_state"; + public virtual string DefaultTemplateIdentifierContext => "cpp_bind_context"; + public abstract string DefaultTemplateContextDefaultType { get; } + public abstract string DefaultTemplateContextDefaultValue { get; } + public virtual ImportedClassTemplateMode DefaultImportedTemplateMode => ImportedClassTemplateMode.Indirect; + public virtual string DefaulCppValidatorFileName => "_cppbind_validator_"; + public virtual string DefaultCmakeVariableHeader => "BINDINGS_HEADER"; + public virtual string DefaultCmakeVariableSource => "BINDINGS_SOURCE"; + public virtual string DefaultEqualityFunctionTemplateFullyQualifiedName => null; + public virtual string DefaultStaticCastFunctionTemplateFullyQualifiedName => null; + public virtual string DefaultDynamicCastFunctionTemplateFullyQualifiedName => null; - public virtual Delegate DefaultBindingIdNamePredicate() - { - return (string name) => - { - return $"_cppbind_id_{name}"; - }; - } - - public virtual Delegate DefaultBindingIdValuePredicate() - { - return (string name) => - { - return $"typeid({name}).name()"; - }; - } - - public virtual Delegate DefaultBindingNamePredicate() + public RegistrableGeneratorOptions() { - return (string name) => - { - return $"_cppbind_{name}"; - }; + OutputSubDir = DefaultOutputSubdir; + RootContextType = DefaultRootContextType; + RootContextName = DefaultRootContextName; + RegisterFunctionName = DefaultRegisterFunctionName; + BaseInclude = DefaultBaseInclude; + BindingIdNamePredicate = DefaultBindingIdNamePredicate; + BindingIdValuePredicate = DefaultBindingIdValuePredicate; + BindingNamePredicate = DefaultBindingNamePredicate; + TemplateTypenameState = DefaultTemplateTypenameState; + TemplateTypenameContext = DefaultTemplateTypenameContext; + TemplateIdentifierState = DefaultTemplateIdentifierState; + TemplateIdentifierContext = DefaultTemplateIdentifierContext; + TemplateContextDefaultType = DefaultTemplateContextDefaultType; + TemplateContextDefaultValue = DefaultTemplateContextDefaultValue; + ImportedTemplateMode = DefaultImportedTemplateMode; + CppValidatorFileName = DefaulCppValidatorFileName; + CmakeVariableHeader = DefaultCmakeVariableHeader; + CmakeVariableSource = DefaultCmakeVariableSource; + EqualityFunctionTemplateFullyQualifiedName = DefaultEqualityFunctionTemplateFullyQualifiedName; + StaticCastFunctionTemplateFullyQualifiedName = DefaultStaticCastFunctionTemplateFullyQualifiedName; + DynamicCastFunctionTemplateFullyQualifiedName = DefaultDynamicCastFunctionTemplateFullyQualifiedName; } } } diff --git a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs index fe7a4537e..3faeca9d9 100644 --- a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs +++ b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs @@ -22,7 +22,7 @@ public bool IsNestedTemplate(Declaration declaration) while (true) { currentDeclaration = currentDeclaration.OriginalNamespace; - if (currentDeclaration != null || currentDeclaration is TranslationUnit) + if (currentDeclaration == null || currentDeclaration is TranslationUnit) { break; } @@ -122,17 +122,17 @@ public virtual string PrintClassTemplateParameter(Declaration declaration, Templ return builder.ToString(); } - public virtual string PrintClassTemplateParameters(ClassTemplate classTemplate, bool includeEnclosingBrackets, TemplateParameterOption option) + public virtual string PrintClassTemplateParameters(List<Declaration> parameters, bool includeEnclosingBrackets, TemplateParameterOption option) { var builder = new StringBuilder(); builder.Append('<'); - for (int i = 0; i < classTemplate.Parameters.Count; i++) + for (int i = 0; i < parameters.Count; i++) { if (i > 0) { builder.Append(", "); } - builder.Append(PrintClassTemplateParameter(classTemplate.Parameters[i], option)); + builder.Append(PrintClassTemplateParameter(parameters[i], option)); } builder.Append('>'); return builder.ToString(); @@ -147,17 +147,17 @@ public virtual string PrintClassTemplateSpecializationArgument(TemplateArgument return templateArgument.Type.Type.Visit(new CppTypePrinter(Generator.Context)); } - public virtual string PrintClassTemplateSpecializationArguments(ClassTemplateSpecialization classTemplateSpecialization, bool includeEnclosingBrackets) + public virtual string PrintClassTemplateSpecializationArguments(List<TemplateArgument> arguments, bool includeEnclosingBrackets) { var builder = new StringBuilder(); builder.Append('<'); - for (int i = 0; i < classTemplateSpecialization.Arguments.Count; i++) + for (int i = 0; i < arguments.Count; i++) { if (i > 0) { builder.Append(", "); } - builder.Append(PrintClassTemplateSpecializationArgument(classTemplateSpecialization.Arguments[i])); + builder.Append(PrintClassTemplateSpecializationArgument(arguments[i])); } builder.Append('>'); return builder.ToString(); @@ -177,7 +177,7 @@ public virtual string GetQualifiedName(Declaration declaration, FQNOption option { if (!option.IgnoreTemplateParameters) { - name = ($"{name}{PrintClassTemplateSpecializationArguments(specialization, true)}"); + name = ($"{name}{PrintClassTemplateSpecializationArguments(specialization.Arguments, true)}"); } } else @@ -190,7 +190,7 @@ public virtual string GetQualifiedName(Declaration declaration, FQNOption option { if (!option.IgnoreTemplateParameters) { - name = ($"{name}{PrintClassTemplateParameters(template, true, TemplateParameterOption.AsArgument)}"); + name = ($"{name}{PrintClassTemplateParameters(template.Parameters, true, TemplateParameterOption.AsArgument)}"); } } } @@ -235,7 +235,7 @@ public virtual string GetFullyQualifiedName(Declaration declaration, FQNOption o { needsTypename = true; } - currentName.Append(PrintClassTemplateSpecializationArguments(specialization, true)); + currentName.Append(PrintClassTemplateSpecializationArguments(specialization.Arguments, true)); } } else @@ -259,7 +259,7 @@ public virtual string GetFullyQualifiedName(Declaration declaration, FQNOption o { needsTypename = true; } - currentName.Append($"{name}{PrintClassTemplateParameters(template, true, TemplateParameterOption.AsArgument)}"); + currentName.Append($"{name}{PrintClassTemplateParameters(template.Parameters, true, TemplateParameterOption.AsArgument)}"); } } } @@ -371,7 +371,7 @@ public virtual string GetBindingContext(Declaration declaration, RegistrableGene var parentList = new List<Declaration>(); while (true) { - if (currentDeclaration != null || currentDeclaration is TranslationUnit) + if (currentDeclaration == null || currentDeclaration is TranslationUnit) { break; } From 45d4043342c57a93643643e58e256807b7580ca9 Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Thu, 14 Dec 2023 18:42:26 +0200 Subject: [PATCH 09/13] Registrable: cleanup --- .../Registrable/Lua/Sol/LuaSolGeneratorOptions.cs | 2 +- .../Generators/Registrable/RegistrableGeneratorOptions.cs | 6 ++++-- .../Generators/Registrable/RegistrableNamingStrategy.cs | 3 +-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs index bf5169eb3..5eb17f8c7 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs @@ -4,7 +4,7 @@ public class LuaSolGeneratorOptions : RegistrableGeneratorOptions { public LuaSolNamingStrategy NamingStrategy; - public LuaSolGeneratorOptions(LuaSolGenerator generator) : base() + public LuaSolGeneratorOptions(LuaSolGenerator generator) : base(generator) { NamingStrategy = new LuaSolNamingStrategy(generator); } diff --git a/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs index 83650e65d..597b1fa0e 100644 --- a/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs +++ b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs @@ -13,7 +13,8 @@ public abstract class RegistrableGeneratorOptions { public delegate string Delegate(string name); - protected Generator generator; + protected Generator Generator; + public virtual string OutputSubDir { get; } public virtual string RootContextType { get; } public virtual string RootContextName { get; } @@ -58,8 +59,9 @@ public abstract class RegistrableGeneratorOptions public virtual string DefaultStaticCastFunctionTemplateFullyQualifiedName => null; public virtual string DefaultDynamicCastFunctionTemplateFullyQualifiedName => null; - public RegistrableGeneratorOptions() + public RegistrableGeneratorOptions(Generator generator) { + Generator = generator; OutputSubDir = DefaultOutputSubdir; RootContextType = DefaultRootContextType; RootContextName = DefaultRootContextName; diff --git a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs index 3faeca9d9..b23e46548 100644 --- a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs +++ b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs @@ -3,7 +3,6 @@ using CppSharp.Generators.Registrable.Lua.Sol; using System.Collections.Generic; using System.Text; -using System.Xml.Linq; namespace CppSharp.Generators.Registrable { @@ -386,7 +385,7 @@ public virtual string GetBindingContext(Declaration declaration, RegistrableGene } } - public string GetCppContext(Declaration entity, RegistrableGeneratorContext context, FQNOption option) + public virtual string GetCppContext(Declaration entity, RegistrableGeneratorContext context, FQNOption option) { if (context != null) { From 9ce5cc631f56f343912e6f238fdcc90c733cf474 Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Fri, 15 Dec 2023 13:50:40 +0200 Subject: [PATCH 10/13] Registrable: generify the API + improvements --- .../Registrable/Lua/Sol/LuaSolGenerator.cs | 24 ++++++------- .../Lua/Sol/LuaSolGeneratorOptions.cs | 2 +- .../Registrable/Lua/Sol/LuaSolHeaders.cs | 15 ++------ .../Registrable/Lua/Sol/LuaSolSources.cs | 24 ++++++------- .../Registrable/RegistrableCodeGenerator.cs | 16 +++++++++ .../Registrable/RegistrableGenerator.cs | 34 +++++++++++++++++++ .../RegistrableGeneratorOptions.cs | 7 ++-- .../Registrable/RegistrableHeaders.cs | 13 +++++++ .../Registrable/RegistrableNamingStrategy.cs | 12 +++++++ .../Registrable/RegistrableSources.cs | 13 +++++++ 10 files changed, 116 insertions(+), 44 deletions(-) create mode 100644 src/Generator/Generators/Registrable/RegistrableCodeGenerator.cs create mode 100644 src/Generator/Generators/Registrable/RegistrableGenerator.cs create mode 100644 src/Generator/Generators/Registrable/RegistrableHeaders.cs create mode 100644 src/Generator/Generators/Registrable/RegistrableSources.cs diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs index 596a4c4b1..ff55e533e 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs @@ -3,32 +3,28 @@ namespace CppSharp.Generators.Registrable.Lua.Sol { - public class LuaSolGenerator : Generator + public class LuaSolGenerator : RegistrableGenerator<LuaSolGeneratorOptions, LuaSolHeaders, LuaSolSources> { public const string Id = "Lua::Sol"; public static readonly GeneratorKind Kind = new(Id, "lua::sol", typeof(LuaSolGenerator), typeof(LuaSolTypePrinter), new[] { "lua::sol" }); - public LuaSolGeneratorOptions GeneratorOptions + public LuaSolGenerator(BindingContext context) : base(context) { - get; } - public LuaSolGenerator(BindingContext context) : base(context) + protected override LuaSolGeneratorOptions CreateOptions(RegistrableGenerator<LuaSolGeneratorOptions, LuaSolHeaders, LuaSolSources> generator) { - GeneratorOptions = new LuaSolGeneratorOptions(this); + return new LuaSolGeneratorOptions(this); } - public override List<CodeGenerator> Generate(IEnumerable<TranslationUnit> units) + protected override LuaSolHeaders CreateHeader(RegistrableGenerator<LuaSolGeneratorOptions, LuaSolHeaders, LuaSolSources> generator, IEnumerable<TranslationUnit> units) { - var outputs = new List<CodeGenerator>(); - - var header = new LuaSolHeaders(this, units); - outputs.Add(header); - - var source = new LuaSolSources(this, units); - outputs.Add(source); + return new LuaSolHeaders(this, units); + } - return outputs; + protected override LuaSolSources CreateSource(RegistrableGenerator<LuaSolGeneratorOptions, LuaSolHeaders, LuaSolSources> generator, IEnumerable<TranslationUnit> units) + { + return new LuaSolSources(this, units); } public override bool SetupPasses() => true; diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs index 5eb17f8c7..1948b7d1d 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs @@ -1,6 +1,6 @@ namespace CppSharp.Generators.Registrable.Lua.Sol { - public class LuaSolGeneratorOptions : RegistrableGeneratorOptions + public class LuaSolGeneratorOptions : RegistrableGeneratorOptions<LuaSolGenerator> { public LuaSolNamingStrategy NamingStrategy; diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs index 971a6fd51..2c648652e 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs @@ -27,22 +27,11 @@ public override void Process() #region TranslationUnit - public override void GenerateTranslationUnitNamespaceBegin(TranslationUnit translationUnit) - { - PushBlock(BlockKind.Namespace); - WriteLine($"namespace {TranslationUnit.Module.OutputNamespace} {{"); - } - - public override void GenerateTranslationUnitNamespaceEnd(TranslationUnit translationUnit) - { - WriteLine($"}} // namespace {TranslationUnit.Module.OutputNamespace}"); - PopBlock(); - } - public virtual void GenerateTranslationUnitRegistrationFunctionDeclaration(TranslationUnit translationUnit) { NewLine(); - WriteLine(GetTranslationUnitRegistrationFunctionSignature(translationUnit)); + GenerateTranslationUnitRegistrationFunctionSignature(translationUnit); + WriteLine(";"); NewLine(); } diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index 03f965e7e..1e8691d06 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -6,16 +6,14 @@ namespace CppSharp.Generators.Registrable.Lua.Sol { - public class LuaSolSources : CodeGenerator + public class LuaSolSources : RegistrableSources<LuaSolGenerator> { - protected LuaSolGenerator Generator { get; } protected LuaSolGenerationContext GenerationContext { get; } protected LuaSolNamingStrategy NamingStrategy => Generator.GeneratorOptions.NamingStrategy; public LuaSolSources(LuaSolGenerator generator, IEnumerable<TranslationUnit> units) - : base(generator.Context, units) + : base(generator, units) { - Generator = generator; GenerationContext = new LuaSolGenerationContext(); } @@ -72,13 +70,12 @@ public virtual void GenerateDeclarationContainerList(DeclarationContext declarat #region TranslationUnit - public virtual string GetTranslationUnitRegistrationFunctionSignature(TranslationUnit translationUnit) + public virtual void GenerateTranslationUnitRegistrationFunctionSignature(TranslationUnit translationUnit) { - StringBuilder builder = new StringBuilder(); - builder.Append("void "); - builder.Append(Generator.GeneratorOptions.NamingStrategy.GetRegistrationFunctionName(translationUnit)); - builder.Append("(::sol::state_view& state) {"); - return builder.ToString(); + var generatorOptions = Generator.GeneratorOptions; + Write("void "); + Write(generatorOptions.NamingStrategy.GetRegistrationFunctionName(translationUnit)); + Write($"({generatorOptions.RootContextType} {generatorOptions.RootContextName})"); } public virtual void GenerateTranslationUnitNamespaceBegin(TranslationUnit translationUnit) @@ -97,7 +94,8 @@ public virtual void GenerateTranslationUnitRegistrationFunctionBegin(Translation { PushBlock(BlockKind.Function); NewLine(); - WriteLine(GetTranslationUnitRegistrationFunctionSignature(translationUnit)); + GenerateTranslationUnitRegistrationFunctionSignature(translationUnit); + WriteLine(" {"); Indent(); } @@ -1194,7 +1192,7 @@ public virtual void GenerateMethod(Class @class, Method method) Write("static_cast<"); Write(method.ReturnType.Visit(new CppTypePrinter(Context))); Write("("); - Write("*)"); + Write($"{NamingStrategy.GetMembershipScopeName(method, GenerationContext)}*)"); Write("("); var needsComma = false; foreach (var parameter in method.Parameters) @@ -1259,7 +1257,7 @@ public virtual void GenerateTypedefNameDecl(TypedefNameDecl typedef) string typedefBindingContext = NamingStrategy.GetBindingContext(typedef, GenerationContext); string typedefRootContextName = NamingStrategy.GetRootContextName(GenerationContext); - WriteLine($"global{typedefRegistrationFunctionName}{{}}({typedefRootContextName}, {typedefBindingContext}, {typedefNameQuoted}); /* directly */"); + WriteLine($"//TODO: global{typedefRegistrationFunctionName}{{}}({typedefRootContextName}, {typedefBindingContext}, {typedefNameQuoted}); /* directly */"); } } diff --git a/src/Generator/Generators/Registrable/RegistrableCodeGenerator.cs b/src/Generator/Generators/Registrable/RegistrableCodeGenerator.cs new file mode 100644 index 000000000..b537d9fe7 --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableCodeGenerator.cs @@ -0,0 +1,16 @@ +using CppSharp.AST; +using System.Collections.Generic; + +namespace CppSharp.Generators.Registrable +{ + public abstract class RegistrableCodeGenerator<TGenerator> : CodeGenerator + where TGenerator : Generator + { + public TGenerator Generator { get; set; } + + public RegistrableCodeGenerator(TGenerator generator, IEnumerable<TranslationUnit> units) : base(generator.Context, units) + { + Generator = generator; + } + } +} diff --git a/src/Generator/Generators/Registrable/RegistrableGenerator.cs b/src/Generator/Generators/Registrable/RegistrableGenerator.cs new file mode 100644 index 000000000..670e111cb --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableGenerator.cs @@ -0,0 +1,34 @@ +using CppSharp.AST; +using System.Collections.Generic; + +namespace CppSharp.Generators.Registrable +{ + public abstract class RegistrableGenerator<TOptions, THeader, TSource> : Generator + where THeader : CodeGenerator + where TSource : CodeGenerator + { + public TOptions GeneratorOptions { get; } + + public RegistrableGenerator(BindingContext context) : base(context) + { + GeneratorOptions = CreateOptions(this); + } + + protected abstract TOptions CreateOptions(RegistrableGenerator<TOptions, THeader, TSource> generator); + + protected abstract THeader CreateHeader(RegistrableGenerator<TOptions, THeader, TSource> generator, IEnumerable<TranslationUnit> units); + + protected abstract TSource CreateSource(RegistrableGenerator<TOptions, THeader, TSource> generator, IEnumerable<TranslationUnit> units); + + public override List<CodeGenerator> Generate(IEnumerable<TranslationUnit> units) + { + return new List<CodeGenerator> + { + CreateHeader(this, units), + CreateSource(this, units) + }; + } + + public override bool SetupPasses() => true; + } +} diff --git a/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs index 597b1fa0e..04dfb8927 100644 --- a/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs +++ b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs @@ -9,11 +9,12 @@ public enum ImportedClassTemplateMode Import } - public abstract class RegistrableGeneratorOptions + public abstract class RegistrableGeneratorOptions<TGenerator> + where TGenerator : Generator { public delegate string Delegate(string name); - protected Generator Generator; + public TGenerator Generator { get; set; } public virtual string OutputSubDir { get; } public virtual string RootContextType { get; } @@ -59,7 +60,7 @@ public abstract class RegistrableGeneratorOptions public virtual string DefaultStaticCastFunctionTemplateFullyQualifiedName => null; public virtual string DefaultDynamicCastFunctionTemplateFullyQualifiedName => null; - public RegistrableGeneratorOptions(Generator generator) + public RegistrableGeneratorOptions(TGenerator generator) { Generator = generator; OutputSubDir = DefaultOutputSubdir; diff --git a/src/Generator/Generators/Registrable/RegistrableHeaders.cs b/src/Generator/Generators/Registrable/RegistrableHeaders.cs new file mode 100644 index 000000000..7ee159fb4 --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableHeaders.cs @@ -0,0 +1,13 @@ +using CppSharp.AST; +using System.Collections.Generic; + +namespace CppSharp.Generators.Registrable +{ + public abstract class RegistrableHeaders<TGenerator> : RegistrableCodeGenerator<TGenerator> + where TGenerator : Generator + { + public RegistrableHeaders(TGenerator generator, IEnumerable<TranslationUnit> units) : base(generator, units) + { + } + } +} diff --git a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs index b23e46548..037fea4eb 100644 --- a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs +++ b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs @@ -397,5 +397,17 @@ public virtual string GetCppContext(Declaration entity, RegistrableGeneratorCont } return GetFullyQualifiedName(entity.OriginalNamespace, option); } + + public virtual string GetMembershipScopeName(Function function, RegistrableGeneratorContext context) + { + if (function is Method method) + { + return GetCppContext(method, context, new FQNOption() + { + IgnoreTemplateTypenameKeyword = true + }) + "::"; + } + return ""; + } } } diff --git a/src/Generator/Generators/Registrable/RegistrableSources.cs b/src/Generator/Generators/Registrable/RegistrableSources.cs new file mode 100644 index 000000000..31c2811c0 --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableSources.cs @@ -0,0 +1,13 @@ +using CppSharp.AST; +using System.Collections.Generic; + +namespace CppSharp.Generators.Registrable +{ + public abstract class RegistrableSources<TGenerator> : RegistrableCodeGenerator<TGenerator> + where TGenerator : Generator + { + public RegistrableSources(TGenerator generator, IEnumerable<TranslationUnit> units) : base(generator, units) + { + } + } +} From 6360b77c7e117b2d2576ad586d15e2b71ae9efc2 Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Sat, 16 Dec 2023 14:38:22 +0200 Subject: [PATCH 11/13] Registrable: add support for class template, imported class + improvements --- .../Registrable/Lua/Sol/LuaSolHeaders.cs | 1 + .../Registrable/Lua/Sol/LuaSolSources.cs | 795 +++++++++++++++++- .../RegistrableGeneratorContext.cs | 9 +- .../Registrable/RegistrableNamingStrategy.cs | 59 +- .../Generators/Registrable/Utils/Utils.cs | 117 ++- 5 files changed, 964 insertions(+), 17 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs index 2c648652e..acc9fe919 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolHeaders.cs @@ -38,6 +38,7 @@ public virtual void GenerateTranslationUnitRegistrationFunctionDeclaration(Trans public override void GenerateTranslationUnit(TranslationUnit translationUnit) { GenerateTranslationUnitNamespaceBegin(translationUnit); + GenerateTranslationUnitRegistrationFunctionBody(translationUnit); GenerateTranslationUnitRegistrationFunctionDeclaration(translationUnit); GenerateTranslationUnitNamespaceEnd(translationUnit); } diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index 1e8691d06..84a468376 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -2,7 +2,6 @@ using CppSharp.Generators.C; using System.Collections.Generic; using System.Linq; -using System.Text; namespace CppSharp.Generators.Registrable.Lua.Sol { @@ -60,12 +59,121 @@ public virtual void GenerateDeclarationGlobalStateRegistration(Declaration decla public virtual void GenerateDeclarationContainerList(DeclarationContext declaration) { - List<Declaration> declarations = declaration.Declarations.Where(declaration => declaration is Namespace || declaration is Class || declaration is Enumeration).ToList(); - declarations.Sort((x, y) => x.LineNumberStart.CompareTo(y.LineNumberStart)); - foreach (var item in declarations) + List<Declaration> containerList = declaration.Declarations.Where(declaration => + { + if (declaration is Namespace || declaration is Enumeration) + { + return true; + } + else if (declaration is Class) + { + return Utils.FindDescribedTemplate(declaration) == null; + } + return false; + }).ToList(); + containerList.Sort((x, y) => x.LineNumberStart.CompareTo(y.LineNumberStart)); + foreach (var item in containerList) { item.Visit(this); }; + + if (NonTemplateAllowed) + { + List<ClassTemplate> classTemplateList = declaration.Templates.Where(template => template is ClassTemplate).Cast<ClassTemplate>().ToList(); + classTemplateList.Sort((x, y) => x.LineNumberStart.CompareTo(y.LineNumberStart)); + foreach (var classTemplate in classTemplateList) + { + if (Utils.IsDefaultTemplateParameterList(classTemplate.Parameters)) + { + Write(string.Format("{0}<>{{}}({1}", + NamingStrategy.GetClassTemplateName(classTemplate), + NamingStrategy.GetRootContextName(GenerationContext) + )); + if (classTemplate.OriginalName != classTemplate.Name) + { + Write(", "); + Write(NamingStrategy.GetRootContextName(GenerationContext)); + Write(", "); + Write(classTemplate.Name); + } + WriteLine(");"); + } + + foreach (var classTemplateSpecialization in classTemplate.Specializations) + { + if (classTemplateSpecialization is not ClassTemplatePartialSpecialization) + { + if (classTemplateSpecialization.SpecializationKind == TemplateSpecializationKind.ExplicitSpecialization) + { + Write(string.Format("{0}<{1}>{{}}({2}", + NamingStrategy.GetClassTemplateName(classTemplateSpecialization), + NamingStrategy.PrintClassTemplateSpecializationArguments(classTemplateSpecialization.Arguments, false), + NamingStrategy.GetRootContextName(GenerationContext) + )); + if (classTemplateSpecialization.OriginalName != classTemplateSpecialization.Name) + { + Write(", "); + Write(NamingStrategy.GetRootContextName(GenerationContext)); + Write(", "); + Write(classTemplateSpecialization.Name); + } + WriteLine(");"); + } + } + } + }; + } + } + + public virtual void GenerateDeclarationTemplateList(DeclarationContext declaration) + { + if (!TemplateAllowed) + { + return; + } + + List<Declaration> containerList = declaration.Declarations.Where(declaration => + { + if (declaration is Namespace || declaration is Enumeration) + { + return true; + } + else if (declaration is Class) + { + return Utils.FindDescribedTemplate(declaration) == null; + } + return false; + }).ToList(); + containerList.Sort((x, y) => x.LineNumberStart.CompareTo(y.LineNumberStart)); + foreach (var item in containerList) + { + if (item.Access == AccessSpecifier.Protected) + { + item.Visit(this); + } + else + { + GenerateDeclarationTemplateList((DeclarationContext)item); + } + }; + + List<ClassTemplate> classTemplateList = declaration.Templates.Where(template => template is ClassTemplate).Cast<ClassTemplate>().ToList(); + classTemplateList.Sort((x, y) => x.LineNumberStart.CompareTo(y.LineNumberStart)); + foreach (var classTemplate in classTemplateList) + { + classTemplate.Visit(this); + foreach (var classTemplateSpecialization in classTemplate.Specializations) + { + classTemplateSpecialization.Visit(this); + } + }; + + //List<Template> functionTemplateList = declaration.Templates.Where(template => template is FunctionTemplate).ToList(); + //functionTemplateList.Sort((x, y) => x.LineNumberStart.CompareTo(y.LineNumberStart)); + //foreach (var item in functionTemplateList) + //{ + // item.Visit(this); + //}; } #region TranslationUnit @@ -101,6 +209,7 @@ public virtual void GenerateTranslationUnitRegistrationFunctionBegin(Translation public virtual void GenerateTranslationUnitRegistrationFunctionBody(TranslationUnit translationUnit) { + GenerateDeclarationTemplateList(translationUnit); GenerateDeclarationContainerList(translationUnit); GenerationContext.Scoped(RegistrableGeneratorContext.IsDetach, DetachmentOption.On, () => @@ -635,6 +744,10 @@ public virtual bool CanGenerateClassDecl(Class @class) { return false; } + else if (@class.IsIncomplete) + { + return false; + } else if (!NonTemplateAllowed) { return false; @@ -648,12 +761,24 @@ public virtual bool CanGenerateClassDecl(Class @class) public override bool VisitClassDecl(Class @class) { - if (!CanGenerateClassDecl(@class)) + if (IsClassDeclImported(@class)) { - return false; + if (!CanGenerateClassDeclImported(@class)) + { + return false; + } + + GenerateClassDeclImported(@class); } + else + { + if (!CanGenerateClassDecl(@class)) + { + return false; + } - GenerateClassDecl(@class); + GenerateClassDecl(@class); + } return true; } @@ -952,6 +1077,10 @@ public virtual bool CanGenerateConstructor(Method constructor) { return false; } + else if (Utils.FindDescribedTemplate(constructor) != null) + { + return false; + } return constructor.IsGenerated; } @@ -1067,11 +1196,16 @@ public virtual bool CanGenerateFunction(Function function) { return false; } + else if (Utils.FindDescribedTemplate(function) != null) + { + return false; + } return function.IsGenerated; } public virtual void GenerateFunction(Declaration declaration, Function function) { + if (Utils.HasPossibleTemplateOverload(function)) { Write("static_cast<"); Write(function.ReturnType.Visit(new CppTypePrinter(Context))); @@ -1104,6 +1238,43 @@ public virtual void GenerateFunction(Declaration declaration, Function function) Write(NamingStrategy.GetContextualName(function, GenerationContext, FQNOption.IgnoreNone)); Write(")"); } + else if (Utils.HasPossibleOverload(function)) + { + Write("::sol::resolve<"); + Write(function.ReturnType.Visit(new CppTypePrinter(Context))); + Write("("); + var needsComma = false; + foreach (var parameter in function.Parameters) + { + if (needsComma) + { + Write(", "); + } + else + { + needsComma = true; + } + Write(parameter.Type.Visit(new CppTypePrinter(Context))); + } + if (function.IsVariadic) + { + if (needsComma) + { + Write(", "); + } + Write("..."); + } + Write(")"); + Write(">(&"); + Write(NamingStrategy.GetContextualName(function, GenerationContext, FQNOption.IgnoreNone)); + Write(")"); + } + else + { + Write(string.Format("&{0}", + NamingStrategy.GetContextualName(function, GenerationContext, FQNOption.IgnoreNone) + )); + } } #endregion @@ -1183,11 +1354,16 @@ public virtual bool CanGenerateMethod(Method method) { return false; } + else if (Utils.FindDescribedTemplate(method) != null) + { + return false; + } return method.IsGenerated; } public virtual void GenerateMethod(Class @class, Method method) { + if (Utils.HasPossibleTemplateOverload(method)) { Write("static_cast<"); Write(method.ReturnType.Visit(new CppTypePrinter(Context))); @@ -1220,6 +1396,43 @@ public virtual void GenerateMethod(Class @class, Method method) Write(NamingStrategy.GetContextualName(method, GenerationContext, FQNOption.IgnoreNone)); Write(")"); } + else if (Utils.HasPossibleOverload(method)) + { + Write("::sol::resolve<"); + Write(method.ReturnType.Visit(new CppTypePrinter(Context))); + Write("("); + var needsComma = false; + foreach (var parameter in method.Parameters) + { + if (needsComma) + { + Write(", "); + } + else + { + needsComma = true; + } + Write(parameter.Type.Visit(new CppTypePrinter(Context))); + } + if (method.IsVariadic) + { + if (needsComma) + { + Write(", "); + } + Write("..."); + } + Write(")"); + Write(">(&"); + Write(NamingStrategy.GetContextualName(method, GenerationContext, FQNOption.IgnoreNone)); + Write(")"); + } + else + { + Write(string.Format("&{0}", + NamingStrategy.GetContextualName(method, GenerationContext, FQNOption.IgnoreNone) + )); + } } #endregion @@ -1284,5 +1497,573 @@ public override bool VisitTypeAliasDecl(TypeAlias typeAlias) } #endregion + + #region Template + + #region ClassDeclImported + + public virtual string GetClassDeclImportedClassType(Class @class) + { + return "auto"; + } + + public virtual void GenerateClassDeclImportedClassValueType(Class @class) + { + var classContextualName = NamingStrategy.GetContextualName(@class, GenerationContext, FQNOption.IgnoreNone); + WriteLine($"using value_type = ::sol::usertype<{classContextualName}>;"); + } + + public virtual void GenerateClassDeclImportedClassBegin(Class @class) + { + WriteLine($"template <typename Importer>"); + WriteLine($"struct {NamingStrategy.GetClassTemplateName(@class)} {{"); + Indent(); + GenerateClassDeclImportedClassValueType(@class); + GenerateDeclarationTemplateList(@class); + WriteLine(string.Format("template <typename {0}, typename {1} = {2}>", + Generator.GeneratorOptions.TemplateTypenameState, + Generator.GeneratorOptions.TemplateTypenameContext, + Generator.GeneratorOptions.TemplateContextDefaultType + )); + WriteLine(string.Format("{0} operator()({1}&& {2}, {3}&& {4} = {5}, const ::std::string& {6} = {{}}) {{", + GetClassDeclImportedClassType(@class), + Generator.GeneratorOptions.TemplateTypenameState, + Generator.GeneratorOptions.TemplateIdentifierState, + Generator.GeneratorOptions.TemplateTypenameContext, + Generator.GeneratorOptions.TemplateIdentifierContext, + Generator.GeneratorOptions.TemplateContextDefaultValue, + "name" + )); + Indent(); + } + + public virtual void GenerateClassDeclImportedClassEnd(Class @class) + { + Unindent(); + WriteLine("}"); + Unindent(); + WriteLine("};"); + } + + public virtual void GenerateClassDeclImportedClassBody(Class @class) + { + var bindingName = NamingStrategy.GetBindingName(@class); + var contextualName = NamingStrategy.GetContextualName(@class, GenerationContext, FQNOption.IgnoreNone); + var fullyQualifiedName = NamingStrategy.GetFullyQualifiedName(@class, FQNOption.IgnoreNone); + var templateIdentifierContext = Generator.GeneratorOptions.TemplateIdentifierContext; + var templateIdentifierState = Generator.GeneratorOptions.TemplateIdentifierState; + + WriteLine(string.Format("const char* {0} = typeid({1}).name();", + "__typeid_name", + contextualName + )); + WriteLine(string.Format("if ({0}[{1}] == ::sol::nil) {{", + templateIdentifierState, + "__typeid_name" + )); + Indent(); + + WriteLine(string.Format("/* FullyQualifiedName: {0} */", + fullyQualifiedName + )); + WriteLine(string.Format("auto {0} = {1}.template new_usertype<{2}>(", + bindingName, + templateIdentifierState, + contextualName + )); + Indent(); + Write("__typeid_name"); + GenerateClassDeclDeclarationList(@class, DetachmentOption.Off); + Unindent(); + NewLine(); + WriteLine(");"); + + Unindent(); + WriteLine("}"); + WriteLine(string.Format("if (!{0}.empty()) {{", + "name" + )); + Indent(); + WriteLine(string.Format("{0}[{1}] = {2}[{3}];", + templateIdentifierContext, + "name", + templateIdentifierState, + "__typeid_name" + )); + Unindent(); + WriteLine("}"); + WriteLine(string.Format("return {0}[{1}];", + templateIdentifierState, + "__typeid_name" + )); + } + + public virtual void GenerateClassDeclImportedClassPushContext(Class @class) + { + GenerationContext.PushTemplateLevel(1); + GenerationContext.PushRootContextName(Generator.GeneratorOptions.TemplateIdentifierState); + GenerationContext.PushCppContext(new CppContext() + { + FullyQualifiedName = string.Format("Importer::template {0}", + NamingStrategy.GetQualifiedName(@class, FQNOption.IgnoreNone) + ), + Option = FQNOption.IgnoreNone + }); + } + + public virtual void GenerateClassDeclImportedClassPopContext(Class @class) + { + GenerationContext.PopCppContext(); + GenerationContext.PopRootContextName(); + GenerationContext.PopTemplateLevel(); + } + + public virtual bool IsClassDeclImported(Class @class) + { + return @class.Access == AccessSpecifier.Protected; + } + + public virtual bool CanGenerateClassDeclImported(Class @class) + { + if (AlreadyVisited(@class)) + { + return false; + } + else if (@class.Access != AccessSpecifier.Protected) + { + return false; + } + else if (@class.IsIncomplete) + { + return false; + } + else if (@class.IsUnion) + { + return false; + } + else if (!TemplateAllowed) + { + return false; + } + else if (Utils.FindDescribedTemplate(@class) != null) + { + return false; + } + return @class.IsGenerated; + } + + public virtual void GenerateClassDeclImported(Class @class) + { + GenerateClassDeclImportedClassPushContext(@class); + + GenerateClassDeclImportedClassBegin(@class); + GenerateClassDeclImportedClassBody(@class); + GenerateClassDeclImportedClassEnd(@class); + + GenerateClassDeclImportedClassPopContext(@class); + } + + #endregion + + #region ClassTemplate + + public virtual string GetClassTemplateDeclFunctorReturnType(ClassTemplate template) + { + return "auto"; + } + + public virtual void GenerateClassTemplateDeclFunctorValueType(ClassTemplate template) + { + var contextualName = NamingStrategy.GetContextualName(template, GenerationContext, FQNOption.IgnoreNone); + + WriteLine(string.Format("using value_type = ::sol::usertype<{0}>;", + contextualName + )); + } + + public virtual void GenerateClassTemplateDeclBegin(ClassTemplate template) + { + Write("template <"); + if (template.Access == AccessSpecifier.Protected) + { + Write("typename Importer>"); + if (template.Parameters.Count > 0) + { + Write(", "); + } + } + Write(NamingStrategy.PrintClassTemplateParameters(template.Parameters, false, TemplateParameterOption.AsParameter)); + WriteLine(">"); + WriteLine($"struct {NamingStrategy.GetClassTemplateName(template)} {{"); + Indent(); + GenerateClassTemplateDeclFunctorValueType(template); + GenerateDeclarationTemplateList(template.TemplatedClass); + WriteLine(string.Format("template <typename {0}, typename {1} = {2}>", + Generator.GeneratorOptions.TemplateTypenameState, + Generator.GeneratorOptions.TemplateTypenameContext, + Generator.GeneratorOptions.TemplateContextDefaultType + )); + WriteLine(string.Format("{0} operator()({1}&& {2}, {3}&& {4} = {5}, const ::std::string& {6} = {{}}) {{", + GetClassTemplateDeclFunctorReturnType(template), + Generator.GeneratorOptions.TemplateTypenameState, + Generator.GeneratorOptions.TemplateIdentifierState, + Generator.GeneratorOptions.TemplateTypenameContext, + Generator.GeneratorOptions.TemplateIdentifierContext, + Generator.GeneratorOptions.TemplateContextDefaultValue, + "name" + )); + Indent(); + } + + public virtual void GenerateClassTemplateDeclEnd(ClassTemplate template) + { + Unindent(); + WriteLine("}"); + Unindent(); + WriteLine("};"); + } + + public virtual void GenerateClassTemplateDeclBody(ClassTemplate template) + { + var bindingName = NamingStrategy.GetBindingName(template); + var contextualName = NamingStrategy.GetContextualName(template, GenerationContext, FQNOption.IgnoreNone); + var fullyQualifiedName = NamingStrategy.GetFullyQualifiedName(template, FQNOption.IgnoreNone); + var templateIdentifierContext = Generator.GeneratorOptions.TemplateIdentifierContext; + var templateIdentifierState = Generator.GeneratorOptions.TemplateIdentifierState; + + WriteLine(string.Format("const char* {0} = typeid({1}).name();", + "__typeid_name", + contextualName + )); + WriteLine(string.Format("if ({0}[{1}] == ::sol::nil) {{", + templateIdentifierState, + "__typeid_name" + )); + Indent(); + + WriteLine(string.Format("/* FullyQualifiedName: {0} */", + fullyQualifiedName + )); + WriteLine(string.Format("auto {0} = {1}.template new_usertype<{2}>(", + bindingName, + templateIdentifierState, + contextualName + )); + Indent(); + Write("__typeid_name"); + GenerateClassDeclDeclarationList(template.TemplatedClass, DetachmentOption.Off); + Unindent(); + NewLine(); + WriteLine(");"); + + Unindent(); + WriteLine("}"); + WriteLine(string.Format("if (!{0}.empty()) {{", + "name" + )); + Indent(); + WriteLine(string.Format("{0}[{1}] = {2}[{3}];", + templateIdentifierContext, + "name", + templateIdentifierState, + "__typeid_name" + )); + Unindent(); + WriteLine("}"); + WriteLine(string.Format("return {0}[{1}];", + templateIdentifierState, + "__typeid_name" + )); + } + + public virtual void GenerateClassTemplateDeclPushContext(ClassTemplate template) + { + GenerationContext.PushTemplateLevel(1); + GenerationContext.PushRootContextName(Generator.GeneratorOptions.TemplateIdentifierState); + if (template.Access == AccessSpecifier.Protected) + { + if (Generator.GeneratorOptions.ImportedTemplateMode == ImportedClassTemplateMode.Indirect) + { + GenerationContext.PushCppContext(new CppContext() + { + FullyQualifiedName = string.Format("Temp_{0}", + NamingStrategy.GetQualifiedName(template, FQNOption.IgnoreNone) + ) + }); + } + else + { + GenerationContext.PushCppContext(new CppContext() + { + FullyQualifiedName = string.Format("Importer::template {0}", + NamingStrategy.GetQualifiedName(template, FQNOption.IgnoreNone) + ) + }); + } + } + } + + public virtual void GenerateClassTemplateDeclPopContext(ClassTemplate template) + { + if (template.Access == AccessSpecifier.Protected) + { + GenerationContext.PopCppContext(); + } + GenerationContext.PopRootContextName(); + GenerationContext.PopTemplateLevel(); + } + + public virtual bool CanGenerateClassTemplateDecl(ClassTemplate template) + { + if (AlreadyVisited(template)) + { + return false; + } + else if (template.Access == AccessSpecifier.Private) + { + return false; + } + else if (template.IsIncomplete) + { + return false; + } + else if (!TemplateAllowed) + { + return false; + } + return template.IsGenerated; + } + + public virtual void GenerateClassTemplateDecl(ClassTemplate template) + { + GenerateClassTemplateDeclPushContext(template); + + GenerateClassTemplateDeclBegin(template); + GenerateClassTemplateDeclBody(template); + GenerateClassTemplateDeclEnd(template); + + GenerateClassTemplateDeclPopContext(template); + } + + public override bool VisitClassTemplateDecl(ClassTemplate template) + { + if (!CanGenerateClassTemplateDecl(template)) + { + return false; + } + + GenerateClassTemplateDecl(template); + + return true; + } + + #endregion + + #region ClassTemplateSpecialization + + public virtual string GetClassTemplateSpecializationDeclFunctorReturnType(ClassTemplateSpecialization specialization) + { + return "auto"; + } + + public virtual void GenerateClassTemplateSpecializationDeclFunctorValueType(ClassTemplateSpecialization specialization) + { + var contextualName = NamingStrategy.GetContextualName(specialization, GenerationContext, FQNOption.IgnoreNone); + + WriteLine(string.Format("using value_type = ::sol::usertype<{0}>;", + contextualName + )); + } + + public virtual void GenerateClassTemplateSpecializationDeclBegin(ClassTemplateSpecialization specialization) + { + Write("template <"); + if (specialization.Access == AccessSpecifier.Protected) + { + Write("typename Importer>"); + if (specialization is ClassTemplatePartialSpecialization) + { + // TODO: provisional and WRONG: see https://github.com/mono/CppSharp/issues/1801 + if (specialization.TemplatedDecl.Parameters.Count > 0) + { + Write(", "); + } + } + } + if (specialization is ClassTemplatePartialSpecialization) + { + // TODO: provisional and WRONG: see https://github.com/mono/CppSharp/issues/1801 + Write(NamingStrategy.PrintClassTemplateParameters(specialization.TemplatedDecl.Parameters, false, TemplateParameterOption.AsParameter)); + } + WriteLine(">"); + WriteLine(string.Format("struct {0}{1} {{", + NamingStrategy.GetClassTemplateName(specialization), + NamingStrategy.PrintClassTemplateSpecializationArguments(specialization.Arguments, true) + )); + Indent(); + GenerateClassTemplateSpecializationDeclFunctorValueType(specialization); + GenerateDeclarationTemplateList(specialization); + WriteLine(string.Format("template <typename {0}, typename {1} = {2}>", + Generator.GeneratorOptions.TemplateTypenameState, + Generator.GeneratorOptions.TemplateTypenameContext, + Generator.GeneratorOptions.TemplateContextDefaultType + )); + WriteLine(string.Format("{0} operator()({1}&& {2}, {3}&& {4} = {5}, const ::std::string& {6} = {{}}) {{", + GetClassTemplateSpecializationDeclFunctorReturnType(specialization), + Generator.GeneratorOptions.TemplateTypenameState, + Generator.GeneratorOptions.TemplateIdentifierState, + Generator.GeneratorOptions.TemplateTypenameContext, + Generator.GeneratorOptions.TemplateIdentifierContext, + Generator.GeneratorOptions.TemplateContextDefaultValue, + "name" + )); + Indent(); + } + + public virtual void GenerateClassTemplateSpecializationDeclEnd(ClassTemplateSpecialization specialization) + { + Unindent(); + WriteLine("}"); + Unindent(); + WriteLine("};"); + } + + public virtual void GenerateClassTemplateSpecializationDeclBody(ClassTemplateSpecialization specialization) + { + var bindingName = NamingStrategy.GetBindingName(specialization); + var contextualName = NamingStrategy.GetContextualName(specialization, GenerationContext, FQNOption.IgnoreNone); + var fullyQualifiedName = NamingStrategy.GetFullyQualifiedName(specialization, FQNOption.IgnoreNone); + var templateIdentifierContext = Generator.GeneratorOptions.TemplateIdentifierContext; + var templateIdentifierState = Generator.GeneratorOptions.TemplateIdentifierState; + + WriteLine(string.Format("const char* {0} = typeid({1}).name();", + "__typeid_name", + contextualName + )); + WriteLine(string.Format("if ({0}[{1}] == ::sol::nil) {{", + templateIdentifierState, + "__typeid_name" + )); + Indent(); + + WriteLine(string.Format("/* FullyQualifiedName: {0} */", + fullyQualifiedName + )); + WriteLine(string.Format("auto {0} = {1}.template new_usertype<{2}>(", + bindingName, + templateIdentifierState, + contextualName + )); + Indent(); + Write("__typeid_name"); + GenerateClassDeclDeclarationList(specialization, DetachmentOption.Off); + Unindent(); + NewLine(); + WriteLine(");"); + + Unindent(); + WriteLine("}"); + WriteLine(string.Format("if (!{0}.empty()) {{", + "name" + )); + Indent(); + WriteLine(string.Format("{0}[{1}] = {2}[{3}];", + templateIdentifierContext, + "name", + templateIdentifierState, + "__typeid_name" + )); + Unindent(); + WriteLine("}"); + WriteLine(string.Format("return {0}[{1}];", + templateIdentifierState, + "__typeid_name" + )); + } + + public virtual void GenerateClassTemplateSpecializationDeclPushContext(ClassTemplateSpecialization specialization) + { + GenerationContext.PushTemplateLevel(1); + GenerationContext.PushRootContextName(Generator.GeneratorOptions.TemplateIdentifierState); + if (specialization.Access == AccessSpecifier.Protected) + { + if (Generator.GeneratorOptions.ImportedTemplateMode == ImportedClassTemplateMode.Indirect) + { + GenerationContext.PushCppContext(new CppContext() + { + FullyQualifiedName = string.Format("Temp_{0}", + NamingStrategy.GetQualifiedName(specialization, FQNOption.IgnoreNone) + ) + }); + } + else + { + GenerationContext.PushCppContext(new CppContext() + { + FullyQualifiedName = string.Format("Importer::template {0}", + NamingStrategy.GetQualifiedName(specialization, FQNOption.IgnoreNone) + ) + }); + } + } + } + + public virtual void GenerateClassTemplateSpecializationDeclPopContext(ClassTemplateSpecialization specialization) + { + if (specialization.Access == AccessSpecifier.Protected) + { + GenerationContext.PopCppContext(); + } + GenerationContext.PopRootContextName(); + GenerationContext.PopTemplateLevel(); + } + + public virtual bool CanGenerateClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization) + { + if (AlreadyVisited(specialization)) + { + return false; + } + else if (specialization.Access == AccessSpecifier.Private) + { + return false; + } + else if (specialization.IsIncomplete) + { + return false; + } + else if (!TemplateAllowed) + { + return false; + } + return specialization.IsGenerated; + } + + public virtual void GenerateClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization) + { + GenerateClassTemplateSpecializationDeclPushContext(specialization); + + GenerateClassTemplateSpecializationDeclBegin(specialization); + GenerateClassTemplateSpecializationDeclBody(specialization); + GenerateClassTemplateSpecializationDeclEnd(specialization); + + GenerateClassTemplateSpecializationDeclPopContext(specialization); + } + + public override bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization) + { + if (!CanGenerateClassTemplateSpecializationDecl(specialization)) + { + return false; + } + + GenerateClassTemplateSpecializationDecl(specialization); + + return true; + } + + #endregion + + #endregion } } diff --git a/src/Generator/Generators/Registrable/RegistrableGeneratorContext.cs b/src/Generator/Generators/Registrable/RegistrableGeneratorContext.cs index 25c1c9ce1..2b55f8f92 100644 --- a/src/Generator/Generators/Registrable/RegistrableGeneratorContext.cs +++ b/src/Generator/Generators/Registrable/RegistrableGeneratorContext.cs @@ -100,13 +100,16 @@ public int PopTemplateLevel() public class CppContext { public string FullyQualifiedName { get; set; } - public FQNOption Option { get; set; } + public FQNOption Option { get; set; } = FQNOption.IgnoreAll; public string GetFullQualifiedName(FQNOption option) { - if (!(Option | option).IgnoreTemplateTypenameKeyword) + if (!option.IgnoreTemplateTypenameKeyword) { - return "typename " + FullyQualifiedName; + if (!Option.IgnoreTemplateTypenameKeyword) + { + return "typename " + FullyQualifiedName; + } } return FullyQualifiedName; } diff --git a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs index 037fea4eb..e831031d5 100644 --- a/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs +++ b/src/Generator/Generators/Registrable/RegistrableNamingStrategy.cs @@ -124,7 +124,10 @@ public virtual string PrintClassTemplateParameter(Declaration declaration, Templ public virtual string PrintClassTemplateParameters(List<Declaration> parameters, bool includeEnclosingBrackets, TemplateParameterOption option) { var builder = new StringBuilder(); - builder.Append('<'); + if (includeEnclosingBrackets) + { + builder.Append('<'); + } for (int i = 0; i < parameters.Count; i++) { if (i > 0) @@ -133,7 +136,10 @@ public virtual string PrintClassTemplateParameters(List<Declaration> parameters, } builder.Append(PrintClassTemplateParameter(parameters[i], option)); } - builder.Append('>'); + if (includeEnclosingBrackets) + { + builder.Append('>'); + } return builder.ToString(); } @@ -149,7 +155,10 @@ public virtual string PrintClassTemplateSpecializationArgument(TemplateArgument public virtual string PrintClassTemplateSpecializationArguments(List<TemplateArgument> arguments, bool includeEnclosingBrackets) { var builder = new StringBuilder(); - builder.Append('<'); + if (includeEnclosingBrackets) + { + builder.Append('<'); + } for (int i = 0; i < arguments.Count; i++) { if (i > 0) @@ -158,7 +167,10 @@ public virtual string PrintClassTemplateSpecializationArguments(List<TemplateArg } builder.Append(PrintClassTemplateSpecializationArgument(arguments[i])); } - builder.Append('>'); + if (includeEnclosingBrackets) + { + builder.Append('>'); + } return builder.ToString(); } @@ -181,9 +193,14 @@ public virtual string GetQualifiedName(Declaration declaration, FQNOption option } else { - if (currentDeclaration is not ClassTemplate template) + Template template = null; + if (currentDeclaration is not ClassTemplate) { - template = (ClassTemplate)Utils.FindDescribedTemplate(currentDeclaration); + var describedTemplate = Utils.FindDescribedTemplate(currentDeclaration); + if (describedTemplate is ClassTemplate) + { + template = (ClassTemplate)describedTemplate; + } } if (template != null) { @@ -287,6 +304,31 @@ public virtual string GetFullyQualifiedName(Declaration declaration, FQNOption o public virtual string GetContextualName(Declaration declaration, RegistrableGeneratorContext context, FQNOption option) { + Class @class = null; + Template template = null; + if (declaration is Class) + { + @class = declaration as Class; + template = Utils.FindDescribedTemplate(declaration); + } + else if (declaration is ClassTemplate classTemplate) + { + @class = classTemplate.TemplatedClass; + template = classTemplate; + } + if (@class is Class) + { + if (template is ClassTemplate) + { + // TODO: check if ClassTemplate is collapsible + } + + if (@class.Access == AccessSpecifier.Protected) + { + return GetCppContext(@class, context, FQNOption.IgnoreNone); + } + return GetFullyQualifiedName(declaration, option); + } return GetCppContext(declaration, context, new FQNOption(false, true, false, false)) + "::" + GetQualifiedName(declaration, option); } @@ -409,5 +451,10 @@ public virtual string GetMembershipScopeName(Function function, RegistrableGener } return ""; } + + public virtual string GetClassTemplateName(Declaration declaration) + { + return $"functor_{GetRegistrationFunctionName(declaration)}"; + } } } diff --git a/src/Generator/Generators/Registrable/Utils/Utils.cs b/src/Generator/Generators/Registrable/Utils/Utils.cs index ef03bbb5c..ebca3efd3 100644 --- a/src/Generator/Generators/Registrable/Utils/Utils.cs +++ b/src/Generator/Generators/Registrable/Utils/Utils.cs @@ -1,10 +1,13 @@ using CppSharp.AST; +using System; +using System.Collections.Generic; +using System.Linq; namespace CppSharp.Generators.Registrable { public static class Utils { - public static Declaration FindDescribedTemplate(Declaration declaration) + public static Template FindDescribedTemplate(Declaration declaration) { foreach (var template in declaration.Namespace.Templates) { @@ -20,5 +23,117 @@ public static DetachmentOption FindDetachmentOption(Declaration declaration) { return (declaration.Namespace is Class) ? DetachmentOption.Off : DetachmentOption.On; } + + public static bool HasPossibleOverload(Function function) + { + var parent = function.OriginalNamespace; + if (parent is Class @class) + { + foreach (var item in @class.Methods) + { + if (item.OriginalFunction == null) + { + if (item != function) + { + if (item.OriginalName == function.Name) + { + return true; + } + } + } + } + foreach (var item in @class.Functions) + { + if (item.OriginalFunction == null) + { + if (item != function) + { + if (item.OriginalName == function.Name) + { + return true; + } + } + } + } + foreach (var item in @class.Templates.Where(template => template is FunctionTemplate).Cast<FunctionTemplate>()) + { + var templatedFunction = item.TemplatedFunction; + if (templatedFunction.OriginalFunction == null) + { + if (templatedFunction != function) + { + if (templatedFunction.OriginalName == function.Name) + { + return true; + } + } + } + } + return false; + } + return true; + } + + public static bool HasPossibleTemplateOverload(Function function) + { + var parent = function.OriginalNamespace; + if (parent is Class @class) + { + foreach (var item in @class.Templates.Where(template => template is FunctionTemplate).Cast<FunctionTemplate>()) + { + var templatedFunction = item.TemplatedFunction; + if (templatedFunction.OriginalFunction == null) + { + if (templatedFunction != function) + { + if (templatedFunction.OriginalName == function.Name) + { + return true; + } + } + } + } + return false; + } + return true; + } + + public static bool HasPossibleTemplateOverload(Method method) + { + if (method.Kind == CXXMethodKind.UsingDirective) + { + return true; + } + return HasPossibleTemplateOverload(method as Function); + } + + public static bool IsDefaultTemplateParameter(Declaration parameter) + { + if (parameter is TypeTemplateParameter typeTemplateParameter) + { + return typeTemplateParameter.DefaultArgument.Type != null; + } + else if (parameter is NonTypeTemplateParameter nonTypeTemplateParameter) + { + return nonTypeTemplateParameter.DefaultArgument != null; + } + else if (parameter is TemplateTemplateParameter templateTemplateParameter) + { + throw new InvalidOperationException(); + } + throw new InvalidOperationException(); + } + + public static bool IsDefaultTemplateParameterList(List<Declaration> parameters) + { + foreach (var parameter in parameters) + { + if (!IsDefaultTemplateParameter(parameter)) + { + return false; + } + } + return true; + } } } From c12d4e7a9a02f088f6ca6d9452a5990e29ee00e7 Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Sun, 17 Dec 2023 17:58:14 +0200 Subject: [PATCH 12/13] LuaSolSources: fix ClassTemplatePartialSpecialization Parameters --- .../Generators/Registrable/Lua/Sol/LuaSolSources.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs index 84a468376..f1a15576b 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolSources.cs @@ -1877,23 +1877,22 @@ public virtual void GenerateClassTemplateSpecializationDeclFunctorValueType(Clas public virtual void GenerateClassTemplateSpecializationDeclBegin(ClassTemplateSpecialization specialization) { + ClassTemplatePartialSpecialization classTemplatePartialSpecialization = specialization as ClassTemplatePartialSpecialization; Write("template <"); if (specialization.Access == AccessSpecifier.Protected) { Write("typename Importer>"); - if (specialization is ClassTemplatePartialSpecialization) + if (classTemplatePartialSpecialization != null) { - // TODO: provisional and WRONG: see https://github.com/mono/CppSharp/issues/1801 - if (specialization.TemplatedDecl.Parameters.Count > 0) + if (classTemplatePartialSpecialization.Parameters.Count > 0) { Write(", "); } } } - if (specialization is ClassTemplatePartialSpecialization) + if (classTemplatePartialSpecialization != null) { - // TODO: provisional and WRONG: see https://github.com/mono/CppSharp/issues/1801 - Write(NamingStrategy.PrintClassTemplateParameters(specialization.TemplatedDecl.Parameters, false, TemplateParameterOption.AsParameter)); + Write(NamingStrategy.PrintClassTemplateParameters(classTemplatePartialSpecialization.Parameters, false, TemplateParameterOption.AsParameter)); } WriteLine(">"); WriteLine(string.Format("struct {0}{1} {{", From 11b37ba40f5f03852d987dcdd3a23900286a52d5 Mon Sep 17 00:00:00 2001 From: Deadlocklogic <deadlocklogic@gmail.com> Date: Sun, 17 Dec 2023 20:57:12 +0200 Subject: [PATCH 13/13] Improve RegistrableGeneratorOptions + prepare boilerplate code --- .../Registrable/Lua/Sol/LuaSolGenerator.cs | 8 ++-- .../Lua/Sol/LuaSolGeneratorOptions.cs | 2 +- .../Registrable/RegistrableGenerator.cs | 44 ++++++++++++++++--- .../RegistrableGeneratorOptions.cs | 17 +++++-- .../Registrable/RegistrableModuleHeader.cs | 19 ++++++++ .../Registrable/RegistrableModuleSource.cs | 19 ++++++++ 6 files changed, 92 insertions(+), 17 deletions(-) create mode 100644 src/Generator/Generators/Registrable/RegistrableModuleHeader.cs create mode 100644 src/Generator/Generators/Registrable/RegistrableModuleSource.cs diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs index ff55e533e..ddb2faeeb 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGenerator.cs @@ -12,21 +12,19 @@ public LuaSolGenerator(BindingContext context) : base(context) { } - protected override LuaSolGeneratorOptions CreateOptions(RegistrableGenerator<LuaSolGeneratorOptions, LuaSolHeaders, LuaSolSources> generator) + protected override LuaSolGeneratorOptions CreateOptions() { return new LuaSolGeneratorOptions(this); } - protected override LuaSolHeaders CreateHeader(RegistrableGenerator<LuaSolGeneratorOptions, LuaSolHeaders, LuaSolSources> generator, IEnumerable<TranslationUnit> units) + protected override LuaSolHeaders CreateHeader(IEnumerable<TranslationUnit> units) { return new LuaSolHeaders(this, units); } - protected override LuaSolSources CreateSource(RegistrableGenerator<LuaSolGeneratorOptions, LuaSolHeaders, LuaSolSources> generator, IEnumerable<TranslationUnit> units) + protected override LuaSolSources CreateSource(IEnumerable<TranslationUnit> units) { return new LuaSolSources(this, units); } - - public override bool SetupPasses() => true; } } diff --git a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs index 1948b7d1d..32531c212 100644 --- a/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs +++ b/src/Generator/Generators/Registrable/Lua/Sol/LuaSolGeneratorOptions.cs @@ -1,6 +1,6 @@ namespace CppSharp.Generators.Registrable.Lua.Sol { - public class LuaSolGeneratorOptions : RegistrableGeneratorOptions<LuaSolGenerator> + public class LuaSolGeneratorOptions : TRegistrableGeneratorOptions<LuaSolGenerator> { public LuaSolNamingStrategy NamingStrategy; diff --git a/src/Generator/Generators/Registrable/RegistrableGenerator.cs b/src/Generator/Generators/Registrable/RegistrableGenerator.cs index 670e111cb..00017d80b 100644 --- a/src/Generator/Generators/Registrable/RegistrableGenerator.cs +++ b/src/Generator/Generators/Registrable/RegistrableGenerator.cs @@ -1,34 +1,64 @@ using CppSharp.AST; using System.Collections.Generic; +using System.IO; namespace CppSharp.Generators.Registrable { public abstract class RegistrableGenerator<TOptions, THeader, TSource> : Generator + where TOptions : RegistrableGeneratorOptions where THeader : CodeGenerator where TSource : CodeGenerator { public TOptions GeneratorOptions { get; } + public TranslationUnit GlobalTranslationUnit { get; private set; } + + public TranslationUnit InheritanceTranslationUnit { get; private set; } + + // TODO: Implement when Generator interface is cleaner + // public CodeGenerator ModuleHeaderCodeGenerator { get; private set; } + + // TODO: Implement when Generator interface is cleaner + //public CodeGenerator ModuleSourceCodeGenerator { get; private set; } + public RegistrableGenerator(BindingContext context) : base(context) { - GeneratorOptions = CreateOptions(this); + GeneratorOptions = CreateOptions(); } - protected abstract TOptions CreateOptions(RegistrableGenerator<TOptions, THeader, TSource> generator); + protected abstract TOptions CreateOptions(); - protected abstract THeader CreateHeader(RegistrableGenerator<TOptions, THeader, TSource> generator, IEnumerable<TranslationUnit> units); + protected abstract THeader CreateHeader(IEnumerable<TranslationUnit> units); - protected abstract TSource CreateSource(RegistrableGenerator<TOptions, THeader, TSource> generator, IEnumerable<TranslationUnit> units); + protected abstract TSource CreateSource(IEnumerable<TranslationUnit> units); public override List<CodeGenerator> Generate(IEnumerable<TranslationUnit> units) { return new List<CodeGenerator> { - CreateHeader(this, units), - CreateSource(this, units) + CreateHeader(units), + CreateSource(units) }; } - public override bool SetupPasses() => true; + // TODO: Should be a better method for this maybe Configure. + public override bool SetupPasses() + { + { + var module = Context.Options.Modules[1]; + GlobalTranslationUnit = Context.ASTContext.FindOrCreateTranslationUnit( + Path.Combine(Context.Options.OutputDir, GeneratorOptions.OutputSubDir, "@package", "global.h") + ); + GlobalTranslationUnit.Module = module; + } + { + var module = Context.Options.Modules[1]; + InheritanceTranslationUnit = Context.ASTContext.FindOrCreateTranslationUnit( + Path.Combine(Context.Options.OutputDir, GeneratorOptions.OutputSubDir, "@package", "inheritance.h") + ); + InheritanceTranslationUnit.Module = module; + } + return true; + } } } diff --git a/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs index 04dfb8927..d8b1b7371 100644 --- a/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs +++ b/src/Generator/Generators/Registrable/RegistrableGeneratorOptions.cs @@ -9,12 +9,11 @@ public enum ImportedClassTemplateMode Import } - public abstract class RegistrableGeneratorOptions<TGenerator> - where TGenerator : Generator + public abstract class RegistrableGeneratorOptions { public delegate string Delegate(string name); - public TGenerator Generator { get; set; } + public virtual Generator Generator { get; set; } public virtual string OutputSubDir { get; } public virtual string RootContextType { get; } @@ -60,7 +59,7 @@ public abstract class RegistrableGeneratorOptions<TGenerator> public virtual string DefaultStaticCastFunctionTemplateFullyQualifiedName => null; public virtual string DefaultDynamicCastFunctionTemplateFullyQualifiedName => null; - public RegistrableGeneratorOptions(TGenerator generator) + public RegistrableGeneratorOptions(Generator generator) { Generator = generator; OutputSubDir = DefaultOutputSubdir; @@ -86,4 +85,14 @@ public RegistrableGeneratorOptions(TGenerator generator) DynamicCastFunctionTemplateFullyQualifiedName = DefaultDynamicCastFunctionTemplateFullyQualifiedName; } } + + public abstract class TRegistrableGeneratorOptions<TGenerator> : RegistrableGeneratorOptions + where TGenerator : Generator + { + public override TGenerator Generator => (TGenerator)base.Generator; + + public TRegistrableGeneratorOptions(TGenerator generator) : base(generator) + { + } + } } diff --git a/src/Generator/Generators/Registrable/RegistrableModuleHeader.cs b/src/Generator/Generators/Registrable/RegistrableModuleHeader.cs new file mode 100644 index 000000000..b9b7ac55d --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableModuleHeader.cs @@ -0,0 +1,19 @@ +using CppSharp.AST; +using System.Collections.Generic; + +namespace CppSharp.Generators.Registrable +{ + public class RegistrableModuleHeader<TGenerator> : RegistrableCodeGenerator<TGenerator> + where TGenerator : Generator + { + public RegistrableModuleHeader(TGenerator generator, IEnumerable<TranslationUnit> units) : base(generator, units) + { + } + + public override string FileExtension { get; } = "h"; + + public override void Process() + { + } + } +} diff --git a/src/Generator/Generators/Registrable/RegistrableModuleSource.cs b/src/Generator/Generators/Registrable/RegistrableModuleSource.cs new file mode 100644 index 000000000..2546fd216 --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableModuleSource.cs @@ -0,0 +1,19 @@ +using CppSharp.AST; +using System.Collections.Generic; + +namespace CppSharp.Generators.Registrable +{ + public class RegistrableModuleSource<TGenerator> : RegistrableCodeGenerator<TGenerator> + where TGenerator : Generator + { + public RegistrableModuleSource(TGenerator generator, IEnumerable<TranslationUnit> units) : base(generator, units) + { + } + + public override string FileExtension { get; } = "cpp"; + + public override void Process() + { + } + } +}