From 8afc2b3e1e1348825ffaffcccf86e6ffeae0c19c Mon Sep 17 00:00:00 2001 From: Deadlocklogic Date: Thu, 14 Dec 2023 08:25:28 +0200 Subject: [PATCH] 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 00000000..60811553 --- /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 00000000..db7766ad --- /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 Generate(IEnumerable units) + { + var outputs = new List(); + + 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 00000000..158cb47b --- /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 00000000..78599525 --- /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 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 00000000..2f26269b --- /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 + { + 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 00000000..410e3f41 --- /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 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 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 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 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 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 00000000..c6c5b51b --- /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 00000000..25c1c9ce --- /dev/null +++ b/src/Generator/Generators/Registrable/RegistrableGeneratorContext.cs @@ -0,0 +1,126 @@ +namespace CppSharp.Generators.Registrable +{ + public class RegistrableGeneratorContext : InfoMapStack + { + 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(IsDetach); + } + + public string PeekRootContextName(string defaultValue = default) + { + return Peek(RootContextName, defaultValue); + } + + public void PushRootContextName(string item) + { + Push(RootContextName, item); + } + + public string PopRootContextName() + { + return Pop(RootContextName); + } + + public string PeekBindingContext(string defaultValue = default) + { + return Peek(BindingContext, defaultValue); + } + + public void PushBindingContext(string item) + { + Push(BindingContext, item); + } + + public string PopBindingContext() + { + return Pop(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); + } + + public int PeekTemplateLevel(int defaultValue = default) + { + return Peek(TemplateLevel, defaultValue); + } + + public void PushTemplateLevel(int item) + { + Push(TemplateLevel, item); + } + + public int PopTemplateLevel() + { + return Pop(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 00000000..7e7e82d1 --- /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 CommonIncludes { get; } + public virtual string OutputSubDir { get; } + public Delegate BindingIdNamePredicate { get; } + public Delegate BindingIdValuePredicate { get; } + public Delegate BindingNamePredicate { get; } + + public RegistrableGeneratorOptions() + { + CommonIncludes = new HashSet(); + 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 00000000..35e38405 --- /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 00000000..9d8bb7f7 --- /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 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(); + 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 00000000..026b0a93 --- /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 00000000..b2055b90 --- /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 + { + public static readonly HashSet 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 00000000..3017d00a --- /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 : Dictionary + { + public InfoMap() : base() + { + } + + public T1 Get(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 00000000..2677386d --- /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 : InfoMap> + { + public InfoMapStack() : base() + { + } + + public T1 Peek(InfoEntry infoEntry, T1 defaultValue = default) where T1 : T + { + if (TryGetValue(infoEntry, out Stack stack)) + { + return (T1)stack.Peek(); + } + return defaultValue; + } + + public T1 Pop(InfoEntry infoEntry) where T1 : T + { + if (TryGetValue(infoEntry, out Stack stack)) + { + return (T1)stack.Pop(); + } + throw new InvalidOperationException(); + } + + public void Push(InfoEntry infoEntry, T1 item) where T1 : T + { + if (!TryGetValue(infoEntry, out Stack stack)) + { + this[infoEntry] = stack = new Stack(); + } + stack.Push(item); + } + + public bool TryPeek(InfoEntry infoEntry, [MaybeNullWhen(false)] out T1 result) where T1 : T + { + if (TryGetValue(infoEntry, out Stack stack)) + { + bool tempReturn = stack.TryPop(out T tempResult); + result = (T1)tempResult; + return tempReturn; + } + result = default; + return false; + } + + public bool TryPop(InfoEntry infoEntry, [MaybeNullWhen(false)] out T1 result) where T1 : T + { + if (TryGetValue(infoEntry, out Stack stack)) + { + bool tempReturn = stack.TryPop(out T tempResult); + result = (T1)tempResult; + return tempReturn; + } + result = default; + return false; + } + + public void Scoped(InfoEntry infoEntry, T1 item, Action action) where T1 : T + { + Push(infoEntry, item); + action(); + Pop(infoEntry); + } + } +} diff --git a/src/Generator/Generators/Registrable/Utils/TemplateParameterOption.cs b/src/Generator/Generators/Registrable/Utils/TemplateParameterOption.cs new file mode 100644 index 00000000..db32620e --- /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 00000000..cff81310 --- /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; + } + } +}