20#include "interfacevisitor.h"
26static std::string Type(std::string src,
const frxml::dom& loc)
29 for (; src[src.size() - 1 - refC] ==
'*'; refC++)
33 src = src.erase(src.length() - refC, refC);
34 std::string ref(refC,
'*');
39 static std::map<std::string, std::string> builtins = {
43 {
"__u16",
"ushort" },
45 {
"__uptr",
"nuint" },
47 {
"__u128",
"System.UInt128" },
53 {
"__s128",
"System.Int128" },
54 {
"__fp16",
"System.Half" },
55 {
"__fp32",
"float" },
56 {
"__fp64",
"double" }
58 if (builtins.contains(src))
59 return builtins[src] + ref;
77> s_GenericInterfaceVisitor;
81 for (
auto i = 0; i < current.children().size(); ++i)
86 s_GenericInterfaceVisitor.Begin(ctx, current, current.children()[i], depth);
87 s_GenericInterfaceVisitor.End(ctx, current, current.children()[i], depth);
91#pragma region AssemblyInterfaceVisitor
95 const frxml::dom& parent,
96 const frxml::dom& current,
99 if (current.tag().view() !=
"assembly")
100 throw shared::exception(
"AssemblyInterfaceVisitor should deal with assembly element only", current);
120 const frxml::dom& parent,
121 const frxml::dom& current,
133#pragma region NamespaceVisitor
142 const frxml::dom& parent,
143 const frxml::dom& current,
149 << indent <<
"namespace " << current.attr().at(
"name").view() <<
shared::endl
157 const frxml::dom& parent,
158 const frxml::dom& current,
167#pragma region RecordVisitor
176 const frxml::dom& parent,
177 const frxml::dom& current,
182 const auto name = current.attr().at(
"name").view();
183 const auto size = current.attr().at(
"size").view();
184 const auto align = current.attr().at(
"align").view();
186#define INTEROP_NS "global::System.Runtime.InteropServices."
187#define LAYOUT_KIND INTEROP_NS "LayoutKind."
188#define COMPILER_NS "global::System.Runtime.CompilerServices."
191 << indent <<
"[" INTEROP_NS"StructLayout(" LAYOUT_KIND"Explicit, Size=" << size <<
", Pack=" << align <<
")]\n"
192 << indent <<
"public struct " << name <<
"\n"
195 << indent <<
TAB "private byte " THIS ";\n"
197 << indent <<
TAB "private IntPtr This\n"
198 << indent <<
TAB "{\n"
199 << indent <<
TAB TAB "get\n"
200 << indent <<
TAB TAB "{\n"
205 << indent <<
TAB TAB "}\n"
206 << indent <<
TAB "}\n";
212 if (!current.children().empty())
220 const frxml::dom& parent,
221 const frxml::dom& current,
230#pragma region EnumVisitor
239 const frxml::dom& parent,
240 const frxml::dom& current,
245 const auto name = current.attr().at(
"name").view();
246 const auto type = current.attr().at(
"type").view();
249 << indent <<
"public enum " << name <<
" : " << Type(
static_cast<std::string
>(type), current) <<
"\n"
257 const frxml::dom& parent,
258 const frxml::dom& current,
267#pragma region EnumConstantVisitor
276 const frxml::dom& parent,
277 const frxml::dom& current,
280 if (parent.tag().view() !=
EnumVisitor().GetName())
281 throw shared::exception(
"`constant' element should be child of `enum' element", current);
285 const auto name = current.attr().at(
"name").view();
286 const auto value = current.attr().at(
"value").view();
293 const frxml::dom& parent,
294 const frxml::dom& current,
308 const frxml::dom& parent,
309 const frxml::dom& current,
314 auto isUnsafe =
false;
317 const auto returnType = Type(
static_cast<std::string
>(current.attr().at(
"return").view()), current);
319 isUnsafe = isUnsafe || returnType.contains(
'*');
323 std::stringstream managedParams;
324 for (
auto i = 0; i < current.children().size(); ++i)
326 if (i) managedParams <<
", ";
328 auto param = current.children().at(i);
329 auto type = Type(
static_cast<std::string
>(param.attr().at(
"type").view()), current.children()[i]);
330 managedParams << type <<
' ' << param.attr().at(
"name").view();
333 std::stringstream nativeParams;
334 for (
auto i = 0; i < current.children().size(); ++i)
336 if (i) nativeParams <<
", ";
338 auto param = current.children().at(i);
339 auto type = Type(
static_cast<std::string
>(param.attr().at(
"type").view()), current.children()[i]);
340 if (!isUnsafe && type.contains(
'*'))
344 "[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.U1)] ";
345 nativeParams << type <<
' ' << param.attr().at(
"name").view();
348 std::stringstream paramRef;
349 for (
auto i = 0; i < current.children().size(); ++i)
351 if (i) paramRef <<
", ";
352 paramRef << current.children().at(i).attr().at(
"name").view();
357#define CALLCONV "System.Runtime.InteropServices.CallingConvention."
358 static std::map<std::string_view, std::string_view> callconvs = {
361 {
"thiscall",
CALLCONV "ThisCall" },
365 auto callconv = current.attr().at(
"callconv").view();
366 if (!callconvs.contains(callconv))
367 throw shared::exception(std::format(
"Calling convention `{}' is not supported", callconv), current);
368 callconv = callconvs.at(callconv);
375 if (!isMemberFn && !isStatic)
378 const auto name = current.attr().at(
"name").view();
380 ctx.
Output << indent <<
"public ";
385 ctx.
Output << returnType <<
' ' << name <<
'(' << managedParams.str() <<
')' <<
shared::endl;
392 if (returnType !=
"void")
397 ctx.
Output <<
"__PInvoke(This";
398 if (!paramRef.str().empty())
399 ctx.
Output <<
", " << paramRef.str();
411 const auto mangling = current.attr().at(
"mangle").view();
413#define INTEROP_NS "System.Runtime.InteropServices."
422 ctx.
Output << indent <<
TAB "static extern " << returnType <<
" __PInvoke(";
425 ctx.
Output <<
"IntPtr @this";
426 if (!nativeParams.str().empty())
436 const frxml::dom& parent,
437 const frxml::dom& current,
void Begin(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
void End(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
A visitor that creates bridge of ctor elements with C#.
std::string GetName() const override
Gets the name of this interface visitor.
A visitor that creates bridge of dtor elements with C#.
std::string GetName() const override
Gets the name of this interface visitor.
A visitor that creates bridge of constant elements with C#.
std::string GetName() const override
Gets the name of this interface visitor.
void End(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
void Begin(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
A visitor that creates bridge of enum elements with C#.
void End(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
void Begin(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
std::string GetName() const override
Gets the name of this interface visitor.
A visitor that creates bridge of function elements with C#.
void Begin(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) final
void End(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) final
std::string GetName() const override
Gets the name of this interface visitor.
A visitor that creates bridge of method elements with C#.
std::string GetName() const override
Gets the name of this interface visitor.
A visitor that creates bridge of namespace elements with C#.
void End(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
void Begin(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
std::string GetName() const override
Gets the name of this interface visitor.
A visitor that creates bridge of record elements with C#.
void End(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
void Begin(VisitContext &ctx, const frxml::dom &parent, const frxml::dom ¤t, int depth) override
std::string GetName() const override
Gets the name of this interface visitor.
A composite ASTVisitor wrapping other ASTVisitor(s)
void ForeachChildren(lilac::csharp::VisitContext &ctx, const frxml::dom ¤t, int depth, bool spacing)
std::ostream & endl(std::ostream &__os)
Write a newline on stream.
constexpr const char * GetIndent(int c=1)
Gets an indentation string with specified length.
std::string RootNamespace