c part ready to go
This commit is contained in:
174
src/Generator.bf
174
src/Generator.bf
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user