fluid
This commit is contained in:
parent
310b0da3de
commit
35fcd147d8
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
@ -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>
|
||||
|
||||
@ -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>;
|
||||
|
||||
48
src/refl/template/refl.liquid
Normal file
48
src/refl/template/refl.liquid
Normal 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
52
src/refl/template/test
Normal 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 %}
|
||||
Loading…
Reference in New Issue
Block a user