This commit is contained in:
ouczbs 2024-04-21 21:44:53 +08:00
parent 310b0da3de
commit 35fcd147d8
11 changed files with 243 additions and 47 deletions

View File

@ -6,25 +6,22 @@ namespace refl
internal class CmdBuildOption
{
[Value(0, MetaName = "", Required = true, Min = 2, HelpText = "Input file(s) for parsing.")]
public IEnumerable<string> InputFiles { get; set; }
public IEnumerable<string>? InputFiles { get; set; }
[Option('o', "output", Required = false, HelpText = "Output file for generated code.")]
public string OutputFile { get; set; }
public string OutputFile { get; set; } = "";
[Option('t', "type", Required = false, HelpText = "Type of code to generate.")]
public string CodeType { get; set; }
public string CodeType { get; set; } = "";
[Option('l', "link", Required = false, HelpText = "link to the include dir")]
public string Link { get; set; }
public string Link { get; set; } = "";
[Option('d', "define", Required = false, HelpText = "define a macro on the command line")]
public string Define { get; set; }
[Option('n', "namespace", Required = false, HelpText = "Namespace for generated code.")]
public string Namespace { get; set; }
public string Define { get; set; } = "";
[Option('h', "help", HelpText = "Display this help message.")]
public bool Help { get; set; }
public bool Help { get; set; } = false;
static CppParserOptions MakeParserOptions(CmdBuildOption opt)
{
@ -54,13 +51,19 @@ namespace refl
}
public static int CMD_CheckBuildOption(CmdBuildOption opt)
{
if(opt.InputFiles == null)
{
return -1;
}
var parse_opt = MakeParserOptions(opt);
var compilation = CppAst.CppParser.ParseFiles(opt.InputFiles.Skip(1).ToList(), parse_opt);
// Print diagnostic messages
foreach (var message in compilation.Diagnostics.Messages)
if(message.Type.Equals(CppLogMessageType.Error))
Console.WriteLine(message);
ModuleMeta.ParseCompileInfo(compilation);
var module = ModuleMeta.ParseCompileInfo(compilation);
ClassMetaGen.GenNameMeta();
ClassMetaGen.GenCppMeta(module);
return 0;
}
}

View File

@ -1,9 +1,4 @@
using CppAst;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace refl
{
@ -33,13 +28,15 @@ namespace refl
internal class ClassMeta
{
public string Name { get; set; }
public string ParentName { get; set; }
public string Path { get; set; }
public Dictionary<string, FieldMeta> Fields { get; set; }
public ClassMeta(string name)
public ClassMeta(string name, string parentName)
{
Name = name;
ParentName = parentName;
Path = "";
Fields = new Dictionary<string, FieldMeta>();
}
@ -58,7 +55,17 @@ namespace refl
}
public static ClassMeta ParseCppClass(CppClass cppClass)
{
ClassMeta cls_meta = new ClassMeta(cppClass.Name);
string parentName = "void";
if (cppClass.BaseTypes.Count == 1)
{
var type = cppClass.BaseTypes[0].Type;
CppClass? parent = type as CppClass;
if (parent != null)
{
parentName = parent.Name;
}
}
ClassMeta cls_meta = new ClassMeta(cppClass.Name, parentName);
foreach (var field in cppClass.Fields)
{
if (field.Attributes.Count == 0)

View File

@ -1,34 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Text;
using Fluid;
namespace refl
{
internal class FieldMetaGenData
{
public string Name { get; set; }
public string Meta { get; set; }
public bool IsMethod { get; set; }
public FieldMetaGenData(string name, string meta, bool isMethod)
{
Name = name;
Meta = meta;
IsMethod = isMethod;
}
}
internal class ClassMetaGenData
{
public string Name { get; set; } = "";
public string NameSpace { get; set; } = "";
public string ParentName { get; set; } = "";
public string Indent { get; set; } = "";
public string MetaName { get; set; } = "";
public List<FieldMetaGenData> FieldList = new List<FieldMetaGenData>();
public ClassMetaGenData(string indent, string nameSpace)
{
Indent = indent;
NameSpace = nameSpace;
}
}
internal class ClassMetaGen
{
public static Dictionary<string, StringBuilder> FileList = new Dictionary<string, StringBuilder>();
public static void GenCppMeta(ModuleMeta module)
public static Fluid.IFluidTemplate? GenTemplate;
public static TemplateOptions GenOptions = new TemplateOptions();
public static void GenNameMeta()
{
foreach(var pair in ModuleMeta.NameMaps)
foreach (var pair in ModuleMeta.NameMaps)
{
FileList.Add(pair.Key, new StringBuilder());
}
foreach(var cls in module.ClassList)
{
var build = new StringBuilder();
build.Append("namespace ");
build.Append(pair.Key);
build.Append("_Name {\n");
foreach(var kv in pair.Value)
{
build.Append(" constexpr const Name ");
build.Append(kv);
build.Append("=\"");
build.Append(kv);
build.Append("\";\n");
}
build.Append("}\n");
Console.WriteLine(build.ToString());
build.Clear();
FileList.Add(pair.Key, build);
}
}
public static void GenClassMeta(ModuleMeta module)
public static void GenCppMeta(ModuleMeta module)
{
var template_string = File.ReadAllText("template/refl.liquid");
var parser = new FluidParser();
parser.TryParse(template_string, out GenTemplate, out var error);
GenOptions.MemberAccessStrategy.Register<FieldMetaGenData>();
if (!string.IsNullOrEmpty(error))
{
Console.WriteLine(error);
return;
}
GenModuleMeta(module, null);
foreach (var pair in FileList)
{
Console.WriteLine(pair.Key);
Console.WriteLine(pair.Value.ToString());
}
}
public static void GenModuleMeta(ModuleMeta module, string? prefix)
{
var gen = new ClassMetaGenData(prefix+"", module.NameSpace);
foreach (var cls in module.ClassList)
{
foreach (var field in cls.Fields)
GenClassMeta(cls, gen);
}
foreach (var child in module.ChildList)
{
if(prefix == null)
{
GenModuleMeta(child, prefix + "\r");
}
else
{
GenModuleMeta(child, prefix + "\t");
}
}
}
public static void GenClassMeta(ClassMeta cls, ClassMetaGenData gen)
{
gen.Name = cls.Name;
gen.ParentName = cls.ParentName;
foreach (var pair in cls.Fields)
{
gen.FieldList.Clear();
foreach (var field in pair.Value.MemberList)
{
gen.FieldList.Add(new FieldMetaGenData(field.Name, field.Meta, false));
}
foreach (var field in pair.Value.MethodList)
{
gen.FieldList.Add(new FieldMetaGenData(field.Name, field.Meta, true));
}
gen.MetaName = pair.Key;
var context = new TemplateContext(gen, GenOptions);
var res = GenTemplate.Render(context);
FileList[pair.Key].Append(res);
}
}
}

View File

@ -1,9 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text;
namespace refl
{
internal class MetaToken

View File

@ -1,9 +1,13 @@
// Parse C++ files
using CppAst;
using CommandLine;
using refl;
Parser.Default.ParseArguments<CmdBuildOption>(args)
class Program
{
static void Main(string[] args)
{
Parser.Default.ParseArguments<CmdBuildOption>(args)
.MapResult(
(CmdBuildOption o) => CmdBuildOption.CMD_CheckBuildOption(o),
error => 1);
error => 1);
}
}

View File

@ -2,7 +2,8 @@
"profiles": {
"refl": {
"commandName": "Project",
"commandLineArgs": "build F:\\csharp\\CppAst.NET\\src\\refl\\cpp\\vertex.h "
"commandLineArgs": "build D:\\csharp\\cppast\\src\\refl\\cpp\\vertex.h ",
"workingDirectory": "D:\\csharp\\cppast\\src\\refl"
}
}
}

View File

@ -1,6 +1,6 @@
#include <iostream>
using namespace std;
namespace test{
struct vec3_parent {
virtual int norm(int x1, int& x2) {
x2 = x1 * x2;
@ -42,5 +42,4 @@ namespace test{
cout << x1 << "::norm3" << endl;
}
};
}
#include "meta.vertex.inl"

View File

@ -8,10 +8,12 @@
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<!-- Workaround for issue https://github.com/microsoft/ClangSharp/issues/129 -->
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == '' AND '$(PackAsTool)' != 'true'">$(NETCoreSdkRuntimeIdentifier)</RuntimeIdentifier>
<StartupObject>Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="Fluid.Core" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

View File

@ -19,7 +19,6 @@ struct vec3_Static_Meta {
return fetch_meta_size<vec3_Static_Meta>();
}
};
constexpr int size = vec3_Static_Meta::Size();
struct vec3_Meta : public Meta{
using MyStatic = vec3_Static_Meta;
using MyUClass = UClass_Meta<vec3, vec3_parent>;

View File

@ -0,0 +1,48 @@
{%- assign indent = Indent -%}
{%- if NameSpace != blank -%}
{{ indent }}namespace {{ NameSpace }} {
{% capture newIndent %}{{ indent }} {% endcapture %}
{%- assign indent = newIndent -%}
{%- endif -%}
{{ indent }}struct {{ Name }}_Static_{{MetaName}} {
{{ indent }} consteval static auto __StaticFields() {
{{ indent }} return std::make_tuple({% for field in FieldList %}&{{Name}}::{{field.Name}}{% unless forloop.last %}, {% endunless %}{% endfor %});
{{ indent }} };
{{ indent }} consteval static auto __MakeStaticFields() {
{{ indent }} return std::array{
{{ indent }} {%- for field in FieldList -%}
{{ indent }} {%- if field.IsMethod -%}
{{ indent }} StaticMethodField(&{{Name}}::{{field.Name}}, {{MetaName}}_Name::{{field.Name}}{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ indent }} {%- else -%}
{{ indent }} StaticMemberField(&{{Name}}::{{field.Name}}, {{MetaName}}_Name::{{field.Name}}{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ indent }} {%- endif -%}
{{ indent }} {%- endfor -%}
{{ indent }} };
{{ indent }} };
{{ indent }} consteval static int Size() {
{{ indent }} return fetch_meta_size<{{ Name }}_Static_{{MetaName}}>();
{{ indent }} };
{{ indent }}};
{{ indent }}struct {{ Name }}_{{MetaName}} : public Meta {
{{ indent }} using MyStatic = {{ Name }}_Static_{{MetaName}};
{{ indent }} using MyUClass = UClass_Meta<{{ Name }}, {{ ParentName }}>;;
{{ indent }} inline static char s_data[MyStatic::Size()]{};
{{ indent }} static auto __MakeFields() {
{{ indent }} char* memory = &s_data[0];
{{ indent }} return std::array{
{{ indent }} {%- for field in FieldList -%}
{{ indent }} {%- if field.IsMethod -%}
{{ indent }} StaticMethodField(&{{Name}}::{{field.Name}}, {{MetaName}}_Name::{{field.Name}}{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ indent }} {%- else -%}
{{ indent }} StaticMemberField(&{{Name}}::{{field.Name}}, {{MetaName}}_Name::{{field.Name}}{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ indent }} {%- endif -%}
{{ indent }} {%- endfor -%}
{{ indent }} };
{{ indent }} };
{{ indent }}};
{% if NameSpace != blank %}
{{ Indent }}}
{% endif %}

52
src/refl/template/test Normal file
View File

@ -0,0 +1,52 @@
{% assign indent = Indent %}
{% if NameSpace %}
{{ indent }}namespace {{ NameSpace }} {
{% capture newIndent %}{{ indent }} {% endcapture %}
{% assign indent = newIndent %}
{% endif %}
{{ indent }}struct {{ Name }}_Static_{{MetaName}} {
{{ indent }} consteval static auto __StaticFields() {
{{ indent }} return std::make_tuple({% for field in FieldList %}&{{Name}}::{{field.Name}}{% unless forloop.last %}, {% endunless %}{% endfor %});
{{ indent }} };
{{ indent }} consteval static auto __MakeStaticFields() {
{{ indent }} return std::array{
{{ indent }} {% for field in FieldList %}
{{ indent }} {% if field.IsMethod %}
{{ indent }} StaticMethodField(&{{field.Name}}, "{{field.Name}}"{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ indent }} {% else %}
{{ indent }} StaticMemberField(&{{field.Name}}, "{{field.Name}}"{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ indent }} {% endif %}
{{ indent }} {% endfor %}
{{ indent }} };
{{ indent }} };
{{ indent }} consteval static int Size() {
{{ indent }} return fetch_meta_size<{{ staticMetaStructName }}>();
{{ indent }} };
{{ indent }}};
{{ indent }}struct {{ Name }}_{{MetaName}} : public Meta {
{{ indent }} using MyStatic = {{ Name }}_Static_{{MetaName}};
{{ indent }} using MyUClass = UClass_Meta<{{ Name }}, {{ ParentName }}>;;
{{ indent }} inline static char s_data[MyStatic::Size()]{};
{{ indent }} static auto __MakeFields() {
{{ indent }} char* memory = &s_data[0];
{{ indent }} return std::array{
{{ indent }} {% for field in FieldList %}
{{ indent }} {% if field.IsMethod %}
{{ indent }} StaticMethodField(&{{field.Name}}, "{{field.Name}}"{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ indent }} {% else %}
{{ indent }} StaticMemberField(&{{field.Name}}, "{{field.Name}}"{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ indent }} {% endif %}
{{ indent }} {% endfor %}
{{ indent }} };
{{ indent }} };
{{ indent }}};
{% if namespace %}
{% for ns in namespace %}
{{ indent }}}
{% capture newIndent %}{{ indent | slice: 0, -4 }}{% endcapture %}
{% assign indent = newIndent %}
{% endfor %}
{% endif %}