rebuild code gen

This commit is contained in:
ouczbs 2024-04-29 01:07:26 +08:00
parent 8a93176b14
commit 9815ea28bb
14 changed files with 320 additions and 196 deletions

View File

@ -58,7 +58,7 @@ namespace refl
}
public static int CMD_CheckBuildOption(CmdBuildOption opt)
{
if(opt.InputFiles == null || !ClassMetaGen.InitTemplate(opt.Template))
if(opt.InputFiles == null || !Gen.InitTemplate(opt.Template))
{
return -1;
}
@ -82,7 +82,8 @@ namespace refl
Console.WriteLine(message);
}
var module = ModuleMeta.ParseCompileInfo(compilation);
ClassMetaGen.GenCppMeta(module, opt.Output.ToLower());
Gen gen = new Gen();
gen.GenCppMeta(module, opt.Output.ToLower());
if (opt.Verbose)
{
Console.WriteLine("gen success!");

View File

@ -1,160 +0,0 @@
using System.IO;
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 Indent2 { get; set; } = "";
public string MetaName { get; set; } = "";
public List<FieldMetaGenData> FieldList = new List<FieldMetaGenData>();
public ClassMetaGenData(string indent, string nameSpace)
{
Indent = indent;
NameSpace = nameSpace;
if (string.IsNullOrEmpty(nameSpace))
{
Indent2 = indent;
}
else
{
Indent2 = indent + "\t";
}
}
}
internal class ClassMetaGen
{
public static Dictionary<string, StringBuilder> FileList = new Dictionary<string, StringBuilder>();
public static Fluid.IFluidTemplate? GenTemplate;
public static TemplateOptions GenOptions = new TemplateOptions();
public static bool InitTemplate(string path)
{
var template_string = File.ReadAllText(path);
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 false;
}
return true;
}
public static void GenCppMeta(ModuleMeta module, string target)
{
foreach (var name in ModuleMeta.NameSet)
{
var build = new StringBuilder();
build.AppendLine("#pragma once");
FileList.Add(name, build);
}
GenModuleMeta(module, null);
string file_name = Path.GetFileName(target);
string? dir = Path.GetDirectoryName(target);
if(dir != null && !Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var output = new StringBuilder();
output.AppendLine("#pragma once");
foreach (var pair in FileList)
{
string path = $"{pair.Key}_{file_name}".ToLower();
output.AppendLine($"#include \"{path}\"");
if (dir != null)
{
path = Path.Combine(dir, path);
}
File.WriteAllText(path, pair.Value.ToString());
}
File.WriteAllText(target, output.ToString());
}
public static void GenModuleMeta(ModuleMeta module, string? prefix)
{
if (!module.HasMeta())
{
return;
}
var gen = new ClassMetaGenData(prefix+"", module.NameSpace);
if (prefix != null)
{
GenNamespaceBegin(gen);
}
foreach (var cls in module.ClassList)
{
GenClassMeta(cls, gen);
}
foreach (var child in module.ChildList)
{
if(prefix == null)
{
GenModuleMeta(child, "");
}
else
{
GenModuleMeta(child, prefix + "\t");
}
}
if (prefix != null)
{
GenNamespaceEnd(gen);
}
}
public static void GenNamespaceBegin(ClassMetaGenData gen)
{
foreach (var name in ModuleMeta.NameSet)
{
string line = $"{gen.Indent}namespace {gen.NameSpace} {{";
FileList[name].AppendLine(line);
}
}
public static void GenNamespaceEnd(ClassMetaGenData gen)
{
foreach (var name in ModuleMeta.NameSet)
{
FileList[name].AppendLine($"{gen.Indent}}}");
}
}
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);
}
}
}
}

119
src/refl/Gen.cs Normal file
View File

@ -0,0 +1,119 @@
using Fluid;
using System.Text;
namespace refl
{
internal class Gen
{
public static Dictionary<string, StringBuilder> FileList = new Dictionary<string, StringBuilder>();
public static StringBuilder Output = new StringBuilder();
private GenMeta meta = new GenMeta();
private GenMultyMeta multyMeta = new GenMultyMeta();
public Gen() { }
public static bool InitTemplate(string dir)
{
string meta_file = Path.Combine(dir, "meta.liquid");
string multy_meta_file = Path.Combine(dir, "meta.liquid");
var parser = new FluidParser();
return GenMeta.InitTemplate(meta_file, parser) && GenMultyMeta.InitTemplate(multy_meta_file, parser);
}
public void CheckDir(string? dir)
{
if (dir != null && !Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
}
public void InitFile(string file_name)
{
Output.AppendLine("#pragma once");
foreach (var name in ModuleMeta.NameSet)
{
var build = new StringBuilder();
build.AppendLine("#pragma once");
FileList.Add(name, build);
if (name == "Meta")
{
string path = $"Meta_{file_name}".ToLower();
Output.AppendLine($"#include \"{path}\"");
}
}
}
public void GenCppMeta(ModuleMeta module, string target)
{
string file_name = Path.GetFileName(target);
string? dir = Path.GetDirectoryName(target);
CheckDir(dir);
InitFile(file_name);
GenModuleMeta(module, null);
OutFile(file_name, dir, target);
}
public void OutFile(string file_name, string? dir,string target)
{
foreach (var pair in FileList)
{
string path = $"{pair.Key}_{file_name}".ToLower();
if (dir != null)
{
path = Path.Combine(dir, path);
}
File.WriteAllText(path, pair.Value.ToString());
}
File.WriteAllText(target, Output.ToString());
}
public void GenModuleMeta(ModuleMeta module, string? prefix)
{
if (!module.HasMeta())
{
return;
}
var data = new ClassMetaData(prefix + "", module.NameSpace);
if (prefix != null)
{
GenNamespaceBegin(data.Indent, data.NameSpace);
}
foreach (var cls in module.ClassList)
{
GenClassMeta(cls, data);
}
string new_prefix = prefix == null ? "" : "\t";
foreach (var child in module.ChildList)
{
GenModuleMeta(child, new_prefix);
}
if (prefix != null)
{
GenNamespaceEnd(data.Indent);
}
}
public void GenClassMeta(ClassMeta cls, ClassMetaData data)
{
meta.GenClassMeta(cls, data);
if (cls.Fields.Count > 0)
{
multyMeta.GenClassMeta(cls, data);
}
}
public static void GenNamespaceBegin(string indent, string name_space)
{
foreach (var name in ModuleMeta.NameSet)
{
string line = $"{indent}namespace {name_space} {{";
FileList[name].AppendLine(line);
}
}
public static void GenNamespaceEnd(string indent)
{
foreach (var name in ModuleMeta.NameSet)
{
FileList[name].AppendLine($"{indent}}}");
}
}
public static void Append(string name, string res)
{
FileList[name].Append(res);
}
}
}

86
src/refl/GenMeta.cs Normal file
View File

@ -0,0 +1,86 @@
using System.IO;
using System.Text;
using Fluid;
namespace refl
{
internal class FieldMetaData
{
public string Name { get; set; }
public string Meta { get; set; }
public bool IsMethod { get; set; }
public FieldMetaData(string name, string meta, bool isMethod)
{
Name = name;
Meta = meta;
IsMethod = isMethod;
}
}
internal class ClassMetaData
{
public string Name { get; set; } = "";
public string NameSpace { get; set; } = "";
public string ParentName { get; set; } = "";
public string Indent { get; set; } = "";
public string Indent2 { get; set; } = "";
public string MetaName { get; set; } = "";
public bool IsMultyMeta { get; set; } = false;
public List<FieldMetaData> FieldList = new List<FieldMetaData>();
public ClassMetaData(string indent, string nameSpace)
{
Indent = indent;
NameSpace = nameSpace;
if (string.IsNullOrEmpty(nameSpace))
{
Indent2 = indent;
}
else
{
Indent2 = indent + "\t";
}
}
}
internal class GenMeta
{
private static IFluidTemplate? template;
private static TemplateOptions options = new TemplateOptions();
public static bool InitTemplate(string path, FluidParser parser)
{
var meta_string = File.ReadAllText(path);
parser.TryParse(meta_string, out template, out var error);
options.MemberAccessStrategy.Register<FieldMetaData>();
if (!string.IsNullOrEmpty(error))
{
Console.WriteLine(error);
return false;
}
return true;
}
public void GenClassMeta(ClassMeta cls, ClassMetaData data)
{
data.Name = cls.Name;
data.ParentName = cls.ParentName;
foreach (var pair in cls.Fields)
{
data.FieldList.Clear();
foreach (var field in pair.Value.MemberList)
{
data.FieldList.Add(new FieldMetaData(field.Name, field.Meta, false));
}
foreach (var field in pair.Value.MethodList)
{
data.FieldList.Add(new FieldMetaData(field.Name, field.Meta, true));
}
data.IsMultyMeta = !pair.Key.Equals("Meta");
data.MetaName = pair.Key;
var context = new TemplateContext(data, options);
var res = template.Render(context);
Gen.Append(pair.Key, res);
}
}
}
}

30
src/refl/GenMultyMeta.cs Normal file
View File

@ -0,0 +1,30 @@
using Fluid;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace refl
{
internal class GenMultyMeta
{
private static IFluidTemplate? template;
private static TemplateOptions options = new TemplateOptions();
public static bool InitTemplate(string path, FluidParser parser)
{
var meta_string = File.ReadAllText(path);
parser.TryParse(meta_string, out template, out var error);
if (!string.IsNullOrEmpty(error))
{
Console.WriteLine(error);
return false;
}
return true;
}
public void GenClassMeta(ClassMeta cls, ClassMetaData data)
{
}
}
}

View File

@ -77,7 +77,7 @@ namespace refl
}
if(key.Length > 0 && value.Length > 0)
{
metas.Add(key.ToString().Trim(), value.ToString().Trim());
metas.Add(key.ToString().Trim(), "{" + value.ToString().Trim()+"}");
}
return metas;
}

View File

@ -2,7 +2,7 @@
"profiles": {
"refl": {
"commandName": "Project",
"commandLineArgs": "build F:\\csharp\\cppast\\src\\refl\\cpp\\vertex.h -o F:\\csharp\\cppast\\src\\refl\\cpp\\gen\\vertex_gen.inl -t F:\\csharp\\cppast\\src\\refl\\template\\refl.liquid -m F:\\csharp\\cppast\\src\\refl\\cpp\\macro.h -v"
"commandLineArgs": "build F:\\csharp\\cppast\\src\\refl\\cpp\\vertex.h -o F:\\csharp\\cppast\\src\\refl\\cpp\\gen\\vertex_gen.inl -t F:\\csharp\\cppast\\src\\refl\\template -m F:\\csharp\\cppast\\src\\refl\\cpp\\macro.h -v"
}
}
}

View File

@ -1,17 +1,15 @@
#pragma once
struct vec3_Static_Meta {
consteval static auto __StaticFields() {
return std::make_tuple(&vec3::z, &vec3::name, &vec3::norm, &vec3::norm1, &vec3::norm2, &vec3::norm3);
return std::make_tuple(&vec3::z, &vec3::name, &vec3::norm, &vec3::norm1);
};
consteval static auto __MakeStaticFields() {
return std::array{
refl::StaticMemberField(&vec3::z, FName("z"), { 5.f }),
refl::StaticMemberField(&vec3::name, FName("name"), { "hello meta" }),
refl::StaticMethodField(&vec3::norm, FName("norm"), { {3,4} }),
refl::StaticMethodField(&vec3::norm1, FName("norm1"), {1}),
refl::StaticMethodField(&vec3::norm2, FName("norm2"), {}),
refl::StaticMethodField(&vec3::norm3, FName("norm3"), {}),
refl::StaticMemberField(&vec3::z, FName("z"), {5.f}),
refl::StaticMemberField(&vec3::name, FName("name"), {"hello meta"}),
refl::StaticMethodField(&vec3::norm, FName("norm"), {{3,4}}),
refl::StaticMethodField(&vec3::norm1, FName("norm1"), {{1}}),
};
};
@ -24,15 +22,14 @@ struct vec3_Meta : public refl::Meta {
using MyStatic = vec3_Static_Meta;
using MyUClass = refl::UClass_Meta<vec3, vec3_parent>;;
inline static char s_data[MyStatic::Size()]{};
static auto __MakeFields() {
char* memory = &s_data[0];
return std::array{
MemberField(&vec3::z, FName("z"), memory, { 5.f }),
MemberField(&vec3::name, FName("name"), memory, { "hello meta" }),
MethodField(&vec3::norm, FName("norm"), memory, { {3,4} }),
MethodField(&vec3::norm1, FName("norm1"), memory, {1}),
MethodField(&vec3::norm2, FName("norm2"), memory, {}),
MethodField(&vec3::norm3, FName("norm3"), memory, {}),
MemberField(&vec3::z, FName("z"), memory, {5.f}),
MemberField(&vec3::name, FName("name"), memory, {"hello meta"}),
MethodField(&vec3::norm, FName("norm"), memory, {{3,4}}),
MethodField(&vec3::norm1, FName("norm1"), memory, {{1}}),
};
};
};

View File

@ -1,3 +1,11 @@
#pragma once
#include "vkmeta_vertex_gen.inl"
#include "meta_vertex_gen.inl"
template<>
struct MultyMeta<vec3> {
const refl::UClass* Meta() {
return &TypeInfo<vec3>::StaticClass;
}
const refl::UClass* vkMeta();
const refl::UClass* GetMeta(const Name& name);
};

View File

@ -6,8 +6,8 @@ struct vec3_Static_vkMeta {
consteval static auto __MakeStaticFields() {
return std::array{
refl::StaticMemberField(&vec3::x, FName("x"), ...),
refl::StaticMemberField(&vec3::y, FName("y"), ...),
refl::StaticMemberField(&vec3::x, FName("x"), {1.f}),
refl::StaticMemberField(&vec3::y, FName("y"), {2.f}),
};
};
@ -20,11 +20,12 @@ struct vec3_vkMeta : public refl::Meta {
using MyStatic = vec3_Static_vkMeta;
using MyUClass = refl::UClass_Meta<vec3, vec3_parent>;;
inline static char s_data[MyStatic::Size()]{};
inline static MyUClass s_cls = MyUClass();
static auto __MakeFields() {
char* memory = &s_data[0];
return std::array{
MemberField(&vec3::x, FName("x"), memory, ...),
MemberField(&vec3::y, FName("y"), memory, ...),
MemberField(&vec3::x, FName("x"), memory, {1.f}),
MemberField(&vec3::y, FName("y"), memory, {2.f}),
};
};
};

View File

@ -5,6 +5,6 @@
#define UFUNCTION(...) __Meta(__VA_ARGS__)
#define __vkMeta(...) __cppast(vkMeta,...)
#define UPROPERTY_vk(...) __vkMeta(...)
#define UFUNCTION_vk(...) __vkMeta(...)
#define __vkMeta(...) __cppast(vkMeta,__VA_ARGS__)
#define UPROPERTY_vk(...) __vkMeta(__VA_ARGS__)
#define UFUNCTION_vk(...) __vkMeta(__VA_ARGS__)

View File

@ -12,15 +12,15 @@ struct vec3_parent {
struct vec3 : public vec3_parent {
using MyMeta = class vec3_Meta;
using MyMetas = MulytMeta<vec3>;
UPROPERTY_vk({ 1.f })
UPROPERTY_vk(1.f)
float x = 1;
UPROPERTY_vk({ 2.f })
UPROPERTY_vk(2.f )
float y = 2;
UPROPERTY({ 5.f })
UPROPERTY(5.f)
float z = 3;
UPROPERTY({ "hello meta" })
UPROPERTY("hello meta")
string name = "???";
UFUNCTION({ {3,4} })
UFUNCTION({3,4})
int norm(int x1, int& x2)override {
int tmp = x1 * 2 + 1;
x1 = x2;
@ -37,11 +37,11 @@ struct vec3 : public vec3_parent {
//cout << x1 << "::norm1" << endl;
return x1;
}
UFUNCTION({})
UFUNCTION()
static void norm2(int x1 = 10) {
cout << x1 << "::norm2" << endl;
}
UFUNCTION({})
UFUNCTION()
static void norm3(int x1 = 10) {
x1 = x1 * 10;
cout << x1 << "::norm3" << endl;

View File

@ -8,9 +8,9 @@
{{ Indent2 }} return std::array{
{{ NewLine }} {%- for field in FieldList -%}
{{ NewLine }} {%- if field.IsMethod -%}
{{ Indent2 }} refl::StaticMethodField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"){% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ Indent2 }} refl::StaticMethodField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}),
{{ NewLine }} {%- else -%}
{{ Indent2 }} refl::StaticMemberField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"){% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ Indent2 }} refl::StaticMemberField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}),
{{ NewLine }} {%- endif -%}
{{ NewLine }} {%- endfor -%}
{{ Indent2 }} };
@ -25,14 +25,15 @@
{{ Indent2 }} using MyStatic = {{ Name }}_Static_{{MetaName}};
{{ Indent2 }} using MyUClass = refl::UClass_Meta<{{ Name }}, {{ ParentName }}>;;
{{ Indent2 }} inline static char s_data[MyStatic::Size()]{};
{{ NewLine }} {%if IsMultyMeta %}inline static MyUClass s_cls = MyUClass();{% endif %}
{{ Indent2 }} static auto __MakeFields() {
{{ Indent2 }} char* memory = &s_data[0];
{{ Indent2 }} return std::array{
{{ NewLine }} {%- for field in FieldList -%}
{{ NewLine }} {%- if field.IsMethod -%}
{{ Indent2 }} MethodField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), memory{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ Indent2 }} MethodField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}),
{{ NewLine }} {%- else -%}
{{ Indent2 }} MemberField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), memory{% if field.Meta %}, {{field.Meta}}{% endif %}),
{{ Indent2 }} MemberField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}),
{{ NewLine }} {%- endif -%}
{{ NewLine }} {%- endfor -%}
{{ Indent2 }} };

View File

@ -0,0 +1,41 @@
{%- assign NewLine = newline_to_br -%}
{{ Indent2 }}struct {{ Name }}_Static_{{MetaName}} {
{{ Indent2 }} consteval static auto __StaticFields() {
{{ Indent2 }} return std::make_tuple({% for field in FieldList %}&{{Name}}::{{field.Name}}{% unless forloop.last %}, {% endunless %}{% endfor %});
{{ Indent2 }} };
{{ NewLine }}
{{ Indent2 }} consteval static auto __MakeStaticFields() {
{{ Indent2 }} return std::array{
{{ NewLine }} {%- for field in FieldList -%}
{{ NewLine }} {%- if field.IsMethod -%}
{{ Indent2 }} refl::StaticMethodField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}),
{{ NewLine }} {%- else -%}
{{ Indent2 }} refl::StaticMemberField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}),
{{ NewLine }} {%- endif -%}
{{ NewLine }} {%- endfor -%}
{{ Indent2 }} };
{{ Indent2 }} };
{{ NewLine }}
{{ Indent2 }} consteval static int Size() {
{{ Indent2 }} return refl::fetch_meta_size<{{ Name }}_Static_{{MetaName}}>();
{{ Indent2 }} };
{{ Indent2 }}};
{{ NewLine }}
{{ Indent2 }}struct {{ Name }}_{{MetaName}} : public refl::Meta {
{{ Indent2 }} using MyStatic = {{ Name }}_Static_{{MetaName}};
{{ Indent2 }} using MyUClass = refl::UClass_Meta<{{ Name }}, {{ ParentName }}>;;
{{ Indent2 }} inline static char s_data[MyStatic::Size()]{};
{{ Indent2 }} static auto __MakeFields() {
{{ Indent2 }} char* memory = &s_data[0];
{{ Indent2 }} return std::array{
{{ NewLine }} {%- for field in FieldList -%}
{{ NewLine }} {%- if field.IsMethod -%}
{{ Indent2 }} MethodField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}),
{{ NewLine }} {%- else -%}
{{ Indent2 }} MemberField(&{{Name}}::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}),
{{ NewLine }} {%- endif -%}
{{ NewLine }} {%- endfor -%}
{{ Indent2 }} };
{{ Indent2 }} };
{{ Indent2 }}};
{{ NewLine }}