c part ready to go

This commit is contained in:
Rune
2026-02-22 15:25:43 +01:00
parent 397c0e320c
commit 806f27381a
17 changed files with 674 additions and 43 deletions

View File

@@ -38,6 +38,8 @@ abstract class Cpp2BeefGenerator
case "uint16_t": outString.Append("uint16");
case "uint32_t": outString.Append("uint32");
case "uint64_t": outString.Append("uint64");
case "intptr_t": outString.Append("c_intptr");
case "uintptr_t": outString.Append("c_uintptr");
default: fallthrough getName;
}
default:
@@ -93,7 +95,7 @@ abstract class Cpp2BeefGenerator
}
}
void WriteBlock(Block block)
protected void WriteBlock(Block block)
{
StringView target;
switch (block)
@@ -131,6 +133,8 @@ abstract class Cpp2BeefGenerator
switch (cursor.kind)
{
case .StructDecl, .ClassDecl, .UnionDecl, .EnumDecl:
if (Clang.Cursor_IsAnonymous(cursor) != 0)
return;
if (templateParams.IsEmpty && Clang.EqualCursors(cursor, Clang.GetTypeDeclaration(Clang.GetCursorType(cursor))) == 0)
return;
BeginCursor(cursor);
@@ -170,7 +174,7 @@ abstract class Cpp2BeefGenerator
MacroDefinition(cursor);
case .InclusionDirective, .MacroExpansion, .CXXBaseSpecifier, .CXXAccessSpecifier,
.LinkageSpec, .TemplateTypeParameter, .NonTypeTemplateParameter: // ignored
.LinkageSpec, .TemplateTypeParameter, .NonTypeTemplateParameter, .StaticAssert: // ignored
default: Debug.WriteLine(scope $"Unhandled cursor: {_}");
}
}
@@ -222,7 +226,8 @@ abstract class Cpp2BeefGenerator
protected class FileInfo : this(CXSourceLocation prevEnd, CXFile file)
{
public append String block = .(64);
public enum { None, LSquirly, RSquirly } queuedToken = .None;
public enum { None = 0, LSquirly = 1, RSquirly = 0b10 } queuedTokens = .None;
public (CXType type, int32 curWidth) bitfield = default;
}
protected FileInfo fileInfo = null;
private Dictionary<String, FileInfo> fileInfos = new .(32) ~ DeleteDictionaryAndKeysAndValues!(_);
@@ -251,6 +256,18 @@ abstract class Cpp2BeefGenerator
ScopeCXString!:mixin(Clang.GetTokenSpelling(unit, token))
}
public static void UpperSnakeCase2PascalCase(StringView snakeCase, String outString)
{
bool upper = true;
for (let c in snakeCase)
if (c == '_') upper = true;
else
{
outString.Append(upper ? c.ToUpper : c.ToLower);
upper = false;
}
}
protected virtual void PreGeneration() {}
protected virtual void PostGeneration() {}
@@ -305,8 +322,8 @@ abstract class Cpp2BeefGenerator
#endif
CXTranslationUnit_Flags unitFlags = .SkipFunctionBodies | .DetailedPreprocessingRecord;
unit = Clang.ParseTranslationUnit(index, headerPath, args.Ptr, (.)args.Length, null, 0, (.)unitFlags);
if (unit == null) return .Err(.ParsingFailed);
if (unit == default) return .Err(.ParsingFailed);
printingPolicy = Clang.GetCursorPrintingPolicy(Clang.GetTranslationUnitCursor(unit));
ModifyWrapperPrintingPolicy(printingPolicy);
defer Clang.PrintingPolicy_Dispose(printingPolicy);
@@ -318,14 +335,14 @@ abstract class Cpp2BeefGenerator
{
let location = Clang.GetCursorLocation(cursor);
Clang.GetSpellingLocation(location, let file, let line, ?, ?);
Clang.GetFileLocation(location, let file, let line, ?, ?);
let header = ScopeCXString!(Clang.GetFileName(file));
self.currentWritter = self.GetWriterForHeader(header);
if (self.currentWritter == null) return .Continue;
if (cursor.kind == .MacroDefinition)
{
self.unitMacros.Add(.(line, file), cursor);
self.unitMacros[.(line, file)] = cursor;
return .Continue;
}
@@ -429,7 +446,7 @@ abstract class Cpp2BeefGenerator
protected void FatalErrorMsg(String outString)
{
Clang.GetSpellingLocation(Clang.GetCursorLocation(currentCursor), let file, let line, let col, ?);
Clang.GetFileLocation(Clang.GetCursorLocation(currentCursor), let file, let line, let col, ?);
outString.Append("in cursor '", GetCursorSpelling!(currentCursor), "' at line ");
outString.AppendF($"{line}:{col}");
outString.Append(" in file ", GetFilePath!(file));
@@ -451,7 +468,7 @@ abstract class Cpp2BeefGenerator
StringView file;
uint32 offset;
{
Clang.GetSpellingLocation(location, let cxfile, ?, ?, out offset);
Clang.GetFileLocation(location, let cxfile, ?, ?, out offset);
char8* ptr = Clang.GetFileContents(unit, cxfile, let size);
file = .(ptr, (.)size);
}
@@ -467,7 +484,7 @@ abstract class Cpp2BeefGenerator
StringView file;
uint32 offset;
{
Clang.GetSpellingLocation(from, let cxfile, ?, ?, out offset);
Clang.GetFileLocation(from, let cxfile, ?, ?, out offset);
char8* ptr = Clang.GetFileContents(unit, cxfile, let size);
file = .(ptr, (.)size);
}
@@ -487,8 +504,8 @@ abstract class Cpp2BeefGenerator
Clang.EqualLocations(end, Clang.GetNullLocation()) != 0) return;
StringView file;
Clang.GetSpellingLocation(start, let startFile, ?, ?, let startOffset);
Clang.GetSpellingLocation(end, let endfile, ?, ?, let endOffset);
Clang.GetFileLocation(start, let startFile, ?, ?, let startOffset);
Clang.GetFileLocation(end, let endfile, ?, ?, let endOffset);
if (Clang.File_IsEqual(startFile, endfile) == 0) return;
char8* ptr = Clang.GetFileContents(unit, startFile, let size);
file = .(ptr, (.)size);
@@ -501,24 +518,35 @@ abstract class Cpp2BeefGenerator
}
}
protected virtual CXSourceLocation GetCursorAnchor(CXCursor cursor)
{
let cursorLocation = Clang.GetCursorLocation(cursor);
//let rangeLocation = Clang.GetRangeStart(Clang.GetCursorExtent(cursor));
//if (Clang.File_IsEqual(Clang.GetSpellingLocation(cursorLocation, file: ..?, ?, ?, ?), Clang.GetSpellingLocation(rangeLocation, file: ..?, ?, ?, ?)) == 0)
return cursorLocation;
//return rangeLocation;
}
protected virtual void WriteComments(CXCursor cursor, Block? block = null)
{
let location = GetCursorAnchor(cursor);
if (cursor.kind == .MacroDefinition)
{
GetIndentation(Clang.GetCursorLocation(cursor), str);
if (block.HasValue) WriteBlock(block.Value);
GetIndentation(location, str);
return;
}
cursorIndent.Clear();
GetIndentation(Clang.GetCursorLocation(cursor), cursorIndent);
WriteComments(Clang.GetCursorLocation(cursor), block);
GetIndentation(location, cursorIndent);
WriteComments(location, block);
}
protected virtual void WriteComments(CXSourceLocation writeUntil, Block? block = null)
{
Clang.GetSpellingLocation(writeUntil, let curFile, let curLine, let curColumn, let curOffset);
Clang.GetSpellingLocation(fileInfo.prevEnd, let prevFile, let prevLine, let prevColumn, let prevOffset);
Clang.GetFileLocation(writeUntil, let curFile, let curLine, let curColumn, let curOffset);
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();
if (Clang.File_IsEqual(curFile, prevFile) == 0) Runtime.FatalError(scope $"{GetFilePath!(curFile)} != {GetFilePath!(prevFile)}");
var between = Clang.GetRange(
Clang.GetLocationForOffset(unit, prevFile, prevOffset),
@@ -579,18 +607,23 @@ abstract class Cpp2BeefGenerator
{
case .Comment:
case .Punctuation:
switch (fileInfo.queuedToken)
mixin QueuedToken(var queuedToken, StringView spelling)
{
case .LSquirly: if (GetTokenSpelling!(token) != "{") continue;
case .RSquirly: if (GetTokenSpelling!(token) != "}") continue;
case .None: continue;
if (fileInfo.queuedTokens.HasFlag(queuedToken) && GetTokenSpelling!(token) == spelling)
{
fileInfo.queuedTokens ^= queuedToken;
isWritingQueuedToken = true;
}
}
fileInfo.queuedToken = .None;
isWritingQueuedToken = true;
QueuedToken!(decltype(fileInfo.queuedTokens).LSquirly, "{");
QueuedToken!(decltype(fileInfo.queuedTokens).RSquirly, "}");
if (!isWritingQueuedToken) continue;
default: continue;
}
let location = Clang.GetTokenLocation(unit, token);
Clang.GetSpellingLocation(location, ?, let startLine, ?, ?);
Clang.GetFileLocation(location, ?, let startLine, ?, ?);
WriteLinesUntil!(startLine, location);
if (!isWritingQueuedToken)
{
@@ -671,6 +704,13 @@ abstract class Cpp2BeefGenerator
case .StructDecl, .ClassDecl, .UnionDecl: Record(decl);
default: Runtime.FatalError(scope $"Unhandled anon type: {_}");
}
if (fileInfo.queuedTokens.HasFlag(.RSquirly))
{
str.Append('\n');
GetIndentation(GetCursorAnchor(decl), str);
str.Append('}');
fileInfo.queuedTokens ^= .RSquirly;
}
break;
}
@@ -751,6 +791,7 @@ abstract class Cpp2BeefGenerator
{
if (Clang.GetTokenKind(token) == .Punctuation && { let spelling = GetTokenSpelling!(token); spelling == "," || spelling == ")" })
{
if (Clang.GetTokenKind(last) != .Identifier) break;
str.Append(' ');
str.Append(GetTokenSpelling!(last));
break;
@@ -779,26 +820,27 @@ abstract class Cpp2BeefGenerator
protected mixin BeginBody(CXCursor cursor)
{
fileInfo.prevEnd = Clang.GetCursorLocation(cursor);
fileInfo.queuedToken = .LSquirly;
fileInfo.prevEnd = GetCursorAnchor(cursor);
fileInfo.queuedTokens |= .LSquirly;
// [Friend] is needed in case you use BeginBody! in your code
if (canChangeBlock)
{
defer:mixin { canChangeBlock = true; }
canChangeBlock = false;
defer:mixin { this.[Friend]canChangeBlock = true; }
this.[Friend]canChangeBlock = false;
}
defer:mixin
{
if (defferedWrapperWrite != null)
if (this.[Friend]defferedWrapperWrite != null)
{
str.Append("\n\n", cursorIndent, "const String _wrapperText = \"\\n\"\n",
defferedWrapperWrite, ";");
delete defferedWrapperWrite;
defferedWrapperWrite = null;
this.[Friend]defferedWrapperWrite, ";");
delete this.[Friend]defferedWrapperWrite;
this.[Friend]defferedWrapperWrite = null;
}
if (fileInfo.queuedToken == .LSquirly)
if (fileInfo.queuedTokens.HasFlag(.LSquirly))
{
switch (cursor.kind)
{
@@ -807,11 +849,10 @@ abstract class Cpp2BeefGenerator
default:
str.Append(" {}");
}
fileInfo.queuedToken = .None;
fileInfo.queuedTokens = .None;
}
else
fileInfo.queuedToken = .RSquirly;
fileInfo.queuedTokens |= .RSquirly;
}
}
@@ -1053,7 +1094,7 @@ abstract class Cpp2BeefGenerator
}
if (Clang.Cursor_IsInlineNamespace(cursor) != 0)
{
GetIndentation(Clang.GetCursorLocation(cursor), str);
GetIndentation(GetCursorAnchor(cursor), str);
str.Append("public static using ");
GetNameInBindings(cursor, str);
str.Append(";\n");
@@ -1215,11 +1256,61 @@ abstract class Cpp2BeefGenerator
str.Append(';');
}
int bitfieldUniquenessCounter = 0;
protected virtual void DumpBitfieldStorage()
{
str.Append("\n", cursorIndent, "private ");
Type(fileInfo.bitfield.type);
str.Append(" __bitfield_");
bitfieldUniquenessCounter++.ToString(str);
str.Append(';');
fileInfo.bitfield = default;
}
protected virtual void FieldDecl(CXCursor cursor)
{
let type = Clang.GetCursorType(cursor);
if (Clang.Cursor_IsBitField(cursor) != 0)
{
if (fileInfo.bitfield.type != default && Clang.EqualTypes(fileInfo.bitfield.type, type) == 0)
DumpBitfieldStorage();
if (fileInfo.bitfield == default)
fileInfo.bitfield.type = type;
int32 width = Clang.GetFieldDeclBitWidth(cursor);
Debug.Assert(width <= Clang.Type_GetSizeOf(type) * 8);
fileInfo.bitfield.curWidth += width;
if (fileInfo.bitfield.curWidth > Clang.Type_GetSizeOf(type) * 8)
{
DumpBitfieldStorage();
fileInfo.bitfield.curWidth = width;
}
str.Append("[Bitfield(.");
if (GetCursorSpelling!(cursor).IsEmpty)
{
str.Append("Private, .Bits(");
width.ToString(str);
str.Append("), \"__anon_bitfield_");
bitfieldUniquenessCounter++.ToString(str);
str.Append("\")]");
}
else
{
Flush();
AccessSpecifier(cursor);
str[0] = str[0].ToUpper;
str.Append(", .Bits(");
width.ToString(str);
str.Append("), \"");
GetNameInBindings(cursor, str);
str.Append("\")]");
}
return;
}
WriteCustomAttributes(cursor);
AccessSpecifier(cursor);
WriteTypeAndName(cursor, Clang.GetCursorType(cursor));
WriteTypeAndName(cursor, type);
str.Append(';');
}
@@ -1380,11 +1471,16 @@ abstract class Cpp2BeefGenerator
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
{
Self self = (.)Internal.UnsafeCastToObject(client_data);
if (self.fileInfo.bitfield != default && Clang.Cursor_IsBitField(cursor) == 0)
self.DumpBitfieldStorage();
self.WriteCursor(cursor);
if (Clang.Cursor_IsAnonymousRecordDecl(cursor) != 0)
self.str..TrimEnd()..Append(";");
return .Continue;
}, Internal.UnsafeCastToPtr(this));
if (fileInfo.bitfield != default)
DumpBitfieldStorage();
}
protected virtual void Enum(CXCursor cursor)