port stub

This commit is contained in:
2026-06-13 18:23:38 +02:00
parent 91ddcd4f79
commit 20b06daa55
+132 -55
View File
@@ -17,6 +17,9 @@ abstract class Cpp2BeefGenerator
{
None = 0,
PreseveColumns = 1,
/// WIP
Port = 2,
}
protected virtual void GetNameInBindings(CXCursor cursor, String outString)
@@ -156,7 +159,7 @@ abstract class Cpp2BeefGenerator
case .FunctionDecl: BeginCursor(cursor); FunctionDecl(cursor);
case .FunctionTemplate, .ClassTemplate, .TypeAliasTemplateDecl:
Runtime.FatalError("Templates are currently unsupported but Coming Soon tm");
Internal.FatalError(scope $"Templates are currently unsupported but Coming Soon tm {FatalErrorMsg(..scope .(256))}");
case .CXXMethod,
.Constructor,
@@ -225,8 +228,10 @@ abstract class Cpp2BeefGenerator
}
protected class FileInfo : this(CXSourceLocation prevEnd, CXFile file)
{
public enum QueuedTokens { None = 0, LSquirly = 1, RSquirly = _<<1, Semicolon = _<<1 }
public append String block = .(64);
public enum { None = 0, LSquirly = 1, RSquirly = _<<1, Semicolon = _<<1 } queuedTokens = .None;
public QueuedTokens queuedTokens = .None;
public (CXType type, int32 curWidth) bitfield = default;
}
protected FileInfo fileInfo = null;
@@ -295,7 +300,8 @@ abstract class Cpp2BeefGenerator
Runtime.FatalError("You must set a language via Args (e.g. --language=c++)");
}
#endif
CXTranslationUnit_Flags unitFlags = .SkipFunctionBodies | .DetailedPreprocessingRecord;
CXTranslationUnit_Flags unitFlags = .DetailedPreprocessingRecord;
if (!Flags.HasFlag(.Port)) unitFlags |= .SkipFunctionBodies;
unit = Clang.ParseTranslationUnit(index, headerPath, args.Ptr, (.)args.Length, null, 0, (.)unitFlags);
if (unit == default) return .Err(.ParsingFailed);
@@ -516,7 +522,8 @@ abstract class Cpp2BeefGenerator
Clang.GetFileLocation(fileInfo.prevEnd, let prevFile, let prevLine, let prevColumn, let prevOffset);
defer { fileInfo.prevEnd = writeUntil; }
if (Clang.File_IsEqual(curFile, prevFile) == 0) Runtime.FatalError(scope $"{GetFilePath!(curFile)} != {GetFilePath!(prevFile)}");
if (!Flags.HasFlag(.Port) && Clang.File_IsEqual(curFile, prevFile) == 0)
Internal.FatalError(scope $"{GetFilePath!(curFile)} does not match {GetFilePath!(prevFile)} {FatalErrorMsg(..scope .(256))}");
var between = Clang.GetRange(
Clang.GetLocationForOffset(unit, prevFile, prevOffset),
@@ -658,7 +665,8 @@ abstract class Cpp2BeefGenerator
fallthrough;
case .RValueReference:
str.Append("in ");
default: Runtime.FatalError();
default:
Internal.FatalError(scope $"Unhandled in-param cursor {FatalErrorMsg(..scope .(256))}");
}
case .OutParam: str.Append("out ");
}
@@ -676,7 +684,7 @@ abstract class Cpp2BeefGenerator
{
case .EnumDecl: Enum(decl);
case .StructDecl, .ClassDecl, .UnionDecl: Record(decl);
default: Runtime.FatalError(scope $"Unhandled anon type: {_}");
default: Internal.FatalError(scope $"Unhandled anon type: {_} {FatalErrorMsg(..scope .(256))}");
}
if (fileInfo.queuedTokens.HasFlag(.RSquirly))
{
@@ -693,7 +701,7 @@ abstract class Cpp2BeefGenerator
String buffer = scope .(256);
GetNameInBindings(decl, qualified);
CXCursor parent = decl;
while (true)
qualify: while (true)
{
parent = Clang.GetCursorSemanticParent(parent);
if (Clang.IsDeclaration(parent.kind) == 0 || parent.kind == .LinkageSpec) break;
@@ -705,22 +713,25 @@ abstract class Cpp2BeefGenerator
buffer.Append('<');
Clang.VisitChildren(parent, (cursor, parent, client_data) =>
{
String buffer = (.)Internal.UnsafeCastToObject(client_data);
(Self self, String buffer) = *(.)client_data;
switch (cursor.kind)
{
case .TemplateTypeParameter, .NonTypeTemplateParameter:
case .TemplateTemplateParameter:
Runtime.FatalError(scope $"C++ template template parameters are not supported");
Internal.FatalError(scope $"C++ template template parameters are not supported {self.FatalErrorMsg(..scope .(256))}");
default: return .Continue;
}
buffer.Append(GetCursorSpelling!(cursor), ", ");
return .Continue;
}, Internal.UnsafeCastToPtr(buffer));
}, &(this, buffer));
buffer.Length -= 2;
buffer.Append('>');
default:
let parentType = Clang.GetCursorType(parent);
if (parentType.kind == .Invalid) break qualify;
Flush();
Type(Clang.GetCursorType(parent));
Type(parentType);
buffer.Append(str);
str.Clear();
}
@@ -737,12 +748,16 @@ abstract class Cpp2BeefGenerator
for (let i < numTemplateArgs)
{
if (i > 0) str.Append(", ");
Type(Clang.Type_GetTemplateArgumentAsType(type, (.)i));
let templateType = Clang.Type_GetTemplateArgumentAsType(type, (.)i);
if (templateType.kind == .Invalid)
str.Append(GetTypeSpelling!(type));
else
Type(templateType);
}
str.Append('>');
}
case .Unexposed, .DependentSizedArray: str.Append(ScopeCXString!(Clang.GetTypeSpelling(Clang.GetUnqualifiedType(type)))); // template param
default: Runtime.FatalError(scope $"Unhandled type: {_} \"{GetTypeSpelling!(type)}\"");
default: Internal.FatalError(scope $"Unhandled type: {_} \"{GetTypeSpelling!(type)}\" {FatalErrorMsg(..scope .(256))}");
}
}
@@ -799,8 +814,14 @@ abstract class Cpp2BeefGenerator
protected mixin BeginBody(CXCursor cursor)
{
static void SetQueuedTokens(FileInfo fileInfo, FileInfo.QueuedTokens queuedTokens)
{
fileInfo.queuedTokens |= queuedTokens;
}
fileInfo.prevEnd = GetCursorAnchor(cursor);
fileInfo.queuedTokens |= .LSquirly;
defer:mixin SetQueuedTokens(fileInfo, fileInfo.queuedTokens);
fileInfo.queuedTokens = .LSquirly;
// [Friend] is needed in case you use BeginBody! in your code
if (canChangeBlock)
@@ -837,8 +858,10 @@ abstract class Cpp2BeefGenerator
}
}
protected virtual enum { C, Cpp } Linkable_Attributes(CXCursor cursor)
protected enum LinkageLanguage { C, Cpp }
protected virtual LinkageLanguage Linkable_Attributes(CXCursor cursor)
{
if (Flags.HasFlag(.Port)) return .C;
let mangledName = ScopeCXString!(Clang.Cursor_GetMangling(cursor));
let name = GetNameInBindings(cursor, ..scope .(mangledName.Length));
WriteCustomAttributes(cursor);
@@ -942,7 +965,7 @@ abstract class Cpp2BeefGenerator
String typeStr = scope .(str);
str.Clear();
str.Append("operator", whitespace, typeStr, templateParams);
case .Ctor: Runtime.FatalError();
case .Ctor: Internal.FatalError(scope $"unhandled ctor {FatalErrorMsg(..scope .(256))}");
case .Dtor: str.Append(whitespace, "Dispose");
}
}
@@ -1075,6 +1098,35 @@ abstract class Cpp2BeefGenerator
}
}
protected virtual void PortCodeBody(CXCursor cursor)
{
if (!Flags.HasFlag(.Port))
{
str.Append(';');
return;
}
var cursor;
if (Clang.IsCursorDefinition(cursor) == 0)
{
cursor = Clang.GetCursorDefinition(cursor);
if (Clang.Cursor_IsNull(cursor) != 0)
{
str.Append(';');
return;
}
}
BeginBody!(@cursor);
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
{
Self self = *(.)client_data;
self.BeginCursor(cursor);
self.str.Append(ScopeCXString!(Clang.GetCursorPrettyPrinted(cursor, self.printingPolicy)));
return .Continue;
}, &(this, default(void)));
}
protected virtual void FunctionDecl(CXCursor cursor)
{
Linkable_Attributes(cursor);
@@ -1085,7 +1137,7 @@ abstract class Cpp2BeefGenerator
Method_Parameters(cursor);
str.Append(')');
str.Append(templateParamsWhere);
str.Append(';');
PortCodeBody(cursor);
}
protected virtual void CXXMethod(CXCursor cursor) //TODO: conversion function
@@ -1100,7 +1152,8 @@ abstract class Cpp2BeefGenerator
{
if (spelling == "operator[]")
{
Runtime.Assert(templateParams.IsEmpty, "Properties can't have generics");
if (!templateParams.IsEmpty)
Internal.FatalError(scope $"Properties can't have generics {FatalErrorMsg(..scope .(256))}");
AccessSpecifier(cursor);
if (Clang.CXXMethod_IsStatic(cursor) != 0) str.Append("static ");
str.Append("extern ");
@@ -1123,7 +1176,7 @@ abstract class Cpp2BeefGenerator
if (str.EndsWith(", ")) str.Length -= 2;
str.Append(')');
str.Append(templateParamsWhere);
str.Append(';');
PortCodeBody(cursor);
return;
}
@@ -1138,7 +1191,7 @@ abstract class Cpp2BeefGenerator
case .CXXMethod:
WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor));
default:
Runtime.FatalError("Unhandled c++ method kind");
Internal.FatalError(scope $"Unhandled c++ method kind {FatalErrorMsg(..scope .(256))}");
}
str.Append('(');
Method_Parameters(cursor);
@@ -1146,7 +1199,7 @@ abstract class Cpp2BeefGenerator
if (Clang.CXXMethod_IsStatic(cursor) == 0 && Clang.CXXMethod_IsConst(cursor) == 0 && cursor.kind == .CXXMethod)
str.Append(" mut");
str.Append(templateParamsWhere);
str.Append(';');
PortCodeBody(cursor);
}
int bitfieldUniquenessCounter = 0;
@@ -1213,24 +1266,30 @@ abstract class Cpp2BeefGenerator
let type = Clang.GetCursorType(cursor);
switch (Clang.GetCursorLinkage(cursor))
{
case .Internal when Clang.IsConstQualifiedType(type) != 0:
case .Internal when Clang.IsConstQualifiedType(type) != 0
|| ScopeCXString!(Clang.GetCursorPrettyPrinted(cursor, printingPolicy)).Contains("constexpr"):
AccessSpecifier(cursor);
str.Append("const ");
WriteTypeAndName(cursor, type);
WriteTokensAfterEquals(cursor);
str.Append(';');
case .External, .UniqueExternal:
Flush();
let linkLang = Linkable_Attributes(cursor);
if (linkLang == .Cpp) str.Clear();
Linkable_Attributes(cursor);
AccessSpecifier(cursor);
str.Append("static extern ");
if (linkLang == .Cpp && type.kind != .LValueReference && type.kind != .RValueReference)
str.Append("ref ");
WriteTypeAndName(cursor, type);
str.Append(';');
default:
Runtime.FatalError(scope $"Unhandled var linkage: {_}");
if (Flags.HasFlag(.Port))
{
AccessSpecifier(cursor);
str.Append("static ");
WriteTypeAndName(cursor, type);
WriteTokensAfterEquals(cursor);
str.Append(';');
}
else
Internal.FatalError(scope $"Unhandled var linkage: {_} {FatalErrorMsg(..scope .(256))}");
}
}
@@ -1254,26 +1313,31 @@ abstract class Cpp2BeefGenerator
protected virtual void Record(CXCursor cursor, bool attributes = true)
{
bool port = Flags.HasFlag(.Port);
WriteCustomAttributes(cursor);
if (attributes)
if (attributes && !port)
switch (cursor.kind)
{
case .StructDecl, .ClassDecl: str.Append("[CRepr] ");
case .UnionDecl: str.Append("[CRepr, Union] ");
default: Runtime.FatalError("Unhandled record type");
default: Internal.FatalError(scope $"Unhandled record type {FatalErrorMsg(..scope .(256))}");
}
AccessSpecifier(cursor);
str.Append("struct ");
if (cursor.kind == .ClassDecl && port)
str.Append("class ");
else
str.Append("struct ");
if (Clang.Cursor_IsAnonymous(cursor) == 0)
GetNameInBindings(cursor, str);
str.Append(templateParams);
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
{
if (cursor.kind != .Destructor) return .Continue;
String str = (.)Internal.UnsafeCastToObject(client_data);
str.Append(" : IDisposable");
return .Break;
}, Internal.UnsafeCastToPtr(str));
if (!port)
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
{
if (cursor.kind != .Destructor) return .Continue;
String str = (.)Internal.UnsafeCastToObject(client_data);
str.Append(" : IDisposable");
return .Break;
}, Internal.UnsafeCastToPtr(str));
str.Append(templateParamsWhere);
BeginBody!(cursor);
@@ -1293,7 +1357,7 @@ abstract class Cpp2BeefGenerator
}
}, Internal.UnsafeCastToPtr(this));*/
if (!wrapperTemplateChain.IsEmpty)
if (!wrapperTemplateChain.IsEmpty && !port)
{
//WriteQueuedOpenSquirly();
str.Append("private const String __cpp_type = \"", GetCursorSpelling!(cursor), "<\"");
@@ -1333,21 +1397,32 @@ abstract class Cpp2BeefGenerator
{
(Self self, bool* firstBase, bool hasVTable) = *(.)client_data;
Runtime.Assert(Clang.IsVirtualBase(cursor) == 0, "Virtual bases are not supported");
//self.WriteQueuedOpenSquirly();
if (*firstBase && hasVTable && !HasVTable(Clang.GetCursorDefinition(cursor)))
self.str.Append(self.cursorIndent, "private void* cppVtable;\n");
self.str.Append(self.cursorIndent);
self.AccessSpecifier(cursor);
self.str.Append("using ");
self.Type(Clang.GetCursorType(cursor));
self.str.Append(";\n");
if (Clang.IsVirtualBase(cursor) != 0)
Internal.FatalError(scope $"Virtual bases are not supported {self.FatalErrorMsg(..scope .(256))}");
if (self.Flags.HasFlag(.Port))
{
if (*firstBase) self.str.Append(" : ");
else self.str.Append(", ");
self.Type(Clang.GetCursorType(cursor));
}
else
{
//self.WriteQueuedOpenSquirly();
if (*firstBase && hasVTable && !HasVTable(Clang.GetCursorDefinition(cursor)))
self.str.Append(self.cursorIndent, "private void* cppVtable;\n");
self.str.Append(self.cursorIndent);
self.AccessSpecifier(cursor);
self.str.Append("using ");
self.Type(Clang.GetCursorType(cursor));
self.str.Append(";\n");
}
*firstBase = false;
return .Continue;
}, &(this, &firstBase, hasVTable));
if (firstBase && hasVTable)
if (firstBase && hasVTable && !port)
str.Append(cursorIndent, "private void* cppVtable;\n");
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
@@ -1362,7 +1437,7 @@ abstract class Cpp2BeefGenerator
{
case .StructDecl, .ClassDecl: self.str.Append("[CRepr] ");
case .UnionDecl: self.str.Append("[CRepr, Union] ");
default: Runtime.FatalError("Unhandled record type");
default: Internal.FatalError(scope $"Unhandled record type {self.FatalErrorMsg(..scope .(256))}");
}
self.AccessSpecifier(cursor);
self.str.Append("using ");
@@ -1401,7 +1476,8 @@ abstract class Cpp2BeefGenerator
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
{
Self self = (.)Internal.UnsafeCastToObject(client_data);
Runtime.Assert(cursor.kind == .EnumConstantDecl);
if (cursor.kind != .EnumConstantDecl)
Internal.FatalError(scope $"Unhandled cursor: {cursor.kind} {self.FatalErrorMsg(..scope .(256))}");
self.HandleCursor(cursor);
return .Continue;
}, Internal.UnsafeCastToPtr(this));
@@ -1422,10 +1498,10 @@ abstract class Cpp2BeefGenerator
CXType type;
switch (cursor.kind)
{
case .TypedefDecl: type = Clang.GetTypedefDeclUnderlyingType(cursor);
case .TypeAliasDecl: type = Clang.GetCursorType(cursor);
case .TypedefDecl, .TypeAliasDecl:
type = Clang.GetTypedefDeclUnderlyingType(cursor);
default:
Runtime.FatalError("Unhandled type alias cursor kind");
Internal.FatalError(scope $"Unhandled type alias cursor kind {FatalErrorMsg(..scope .(256))}");
}
if (type.kind == .Pointer) do
@@ -1447,7 +1523,8 @@ abstract class Cpp2BeefGenerator
AccessSpecifier(cursor);
str.Append("typealias");
WriteTypeAndName(cursor, type, .TypeAlias);
Runtime.Assert(templateParamsWhere.IsEmpty, "type aliases can't have constraints (yet)");
if (!templateParamsWhere.IsEmpty)
Internal.FatalError(scope $"type aliases can't have constraints (yet) {FatalErrorMsg(..scope .(256))}");
}
protected virtual void MacroDefinition(CXCursor cursor)