discont ports & change token queueing

This commit is contained in:
2026-06-22 15:54:20 +02:00
parent f3184ed633
commit 3d9a9cd158
+92 -136
View File
@@ -17,9 +17,6 @@ abstract class Cpp2BeefGenerator
{ {
None = 0, None = 0,
PreseveColumns = 1, PreseveColumns = 1,
/// WIP
Port = 2,
} }
protected virtual void GetNameInBindings(CXCursor cursor, String outString) protected virtual void GetNameInBindings(CXCursor cursor, String outString)
@@ -182,8 +179,11 @@ abstract class Cpp2BeefGenerator
MacroDefinition(cursor); MacroDefinition(cursor);
case .InclusionDirective, .MacroExpansion, .CXXBaseSpecifier, .CXXAccessSpecifier, case .InclusionDirective, .MacroExpansion, .CXXBaseSpecifier, .CXXAccessSpecifier,
.LinkageSpec, .TemplateTypeParameter, .NonTypeTemplateParameter, .StaticAssert: // ignored .LinkageSpec, .TemplateTypeParameter, .NonTypeTemplateParameter, .StaticAssert,
default: Debug.WriteLine(scope $"Unhandled cursor: {_}"); .UsingDeclaration, .UnexposedDecl, .FriendDecl: // ignored
default:
if (Clang.IsAttribute(_) == 0)
Debug.WriteLine(scope $"Unhandled cursor: {_}");
} }
} }
@@ -217,8 +217,8 @@ abstract class Cpp2BeefGenerator
private StreamWriter currentWritter; private StreamWriter currentWritter;
private append String wrapperTemplateChain = .(16); private append String wrapperTemplateChain = .(16);
private append String templateParams = .(16); public append String templateParams = .(16);
private append String templateParamsWhere = .(64); public append String templateParamsWhere = .(64);
private String defferedWrapperWrite = null; private String defferedWrapperWrite = null;
private struct UnitMacroIndex : this(uint32 line, CXFile file), IHashable private struct UnitMacroIndex : this(uint32 line, CXFile file), IHashable
@@ -228,10 +228,13 @@ abstract class Cpp2BeefGenerator
} }
protected class FileInfo : this(CXSourceLocation prevEnd, CXFile file) protected class FileInfo : this(CXSourceLocation prevEnd, CXFile file)
{ {
public enum QueuedTokens { None = 0, LSquirly = 1, RSquirly = _<<1, Semicolon = _<<1 } public uint queuedRSquirly = 0;
public uint queuedLSquirly = 0;
public uint queuedSemicolon = 0;
public bool NoTokensQueued =>
queuedLSquirly == 0 && queuedRSquirly == 0 && queuedSemicolon == 0;
public append String block = .(64); public append String block = .(64);
public QueuedTokens queuedTokens = .None;
public (CXType type, int32 curWidth) bitfield = default; public (CXType type, int32 curWidth) bitfield = default;
} }
protected FileInfo fileInfo = null; protected FileInfo fileInfo = null;
@@ -300,8 +303,7 @@ abstract class Cpp2BeefGenerator
Runtime.FatalError("You must set a language via Args (e.g. --language=c++)"); Runtime.FatalError("You must set a language via Args (e.g. --language=c++)");
} }
#endif #endif
CXTranslationUnit_Flags unitFlags = .DetailedPreprocessingRecord; CXTranslationUnit_Flags unitFlags = .DetailedPreprocessingRecord | .SkipFunctionBodies;
if (!Flags.HasFlag(.Port)) unitFlags |= .SkipFunctionBodies;
unit = Clang.ParseTranslationUnit(index, headerPath, args.Ptr, (.)args.Length, null, 0, (.)unitFlags); unit = Clang.ParseTranslationUnit(index, headerPath, args.Ptr, (.)args.Length, null, 0, (.)unitFlags);
if (unit == default) return .Err(.ParsingFailed); if (unit == default) return .Err(.ParsingFailed);
@@ -516,13 +518,13 @@ abstract class Cpp2BeefGenerator
protected virtual void WriteComments(CXSourceLocation writeUntil, Block? block = null) protected virtual void WriteComments(CXSourceLocation writeUntil, Block? block = null)
{ {
var block; var block;
if (fileInfo.queuedTokens != .None) block = null; if (!fileInfo.NoTokensQueued) block = null;
Clang.GetFileLocation(writeUntil, let curFile, let curLine, let curColumn, let curOffset); Clang.GetFileLocation(writeUntil, let curFile, let curLine, let curColumn, let curOffset);
Clang.GetFileLocation(fileInfo.prevEnd, let prevFile, let prevLine, let prevColumn, let prevOffset); Clang.GetFileLocation(fileInfo.prevEnd, let prevFile, let prevLine, let prevColumn, let prevOffset);
defer { fileInfo.prevEnd = writeUntil; } defer { fileInfo.prevEnd = writeUntil; }
if (!Flags.HasFlag(.Port) && Clang.File_IsEqual(curFile, prevFile) == 0) if (Clang.File_IsEqual(curFile, prevFile) == 0)
Internal.FatalError(scope $"{GetFilePath!(curFile)} does not match {GetFilePath!(prevFile)} {FatalErrorMsg(..scope .(256))}"); Internal.FatalError(scope $"{GetFilePath!(curFile)} does not match {GetFilePath!(prevFile)} {FatalErrorMsg(..scope .(256))}");
var between = Clang.GetRange( var between = Clang.GetRange(
@@ -564,7 +566,7 @@ abstract class Cpp2BeefGenerator
void Block() void Block()
{ {
if (fileInfo.queuedTokens != .None) return; if (!fileInfo.NoTokensQueued) return;
findMacros: do findMacros: do
{ {
for (uint32 ln = line; ln < curLine; ln++) for (uint32 ln = line; ln < curLine; ln++)
@@ -578,11 +580,34 @@ abstract class Cpp2BeefGenerator
} }
bool first = true; bool first = true;
bool isWritingQueuedToken = false;
for (let token in tokens) for (let token in tokens)
{ {
if (!FilterTokensBetweenCursors(token, let isWritingQueuedToken)) bool prevWritingQueuedToken = isWritingQueuedToken;
isWritingQueuedToken = false;
switch (Clang.GetTokenKind(token))
{
case .Comment:
case .Punctuation:
mixin QueuedToken(ref uint queuedToken, StringView spelling)
{
if (queuedToken > 0 && GetTokenSpelling!(token) == spelling)
{
isWritingQueuedToken = true;
queuedToken--;
}
}
QueuedToken!(ref fileInfo.queuedLSquirly, "{");
QueuedToken!(ref fileInfo.queuedRSquirly, "}");
if (prevWritingQueuedToken) // only write a semicolon after a '}'
QueuedToken!(ref fileInfo.queuedSemicolon, ";");
if (!isWritingQueuedToken) continue;
default:
continue; continue;
if (isWritingQueuedToken && fileInfo.queuedTokens == .None) }
if (isWritingQueuedToken && fileInfo.NoTokensQueued)
block = @block; block = @block;
let location = Clang.GetTokenLocation(unit, token); let location = Clang.GetTokenLocation(unit, token);
Clang.GetFileLocation(location, ?, let startLine, ?, ?); Clang.GetFileLocation(location, ?, let startLine, ?, ?);
@@ -602,34 +627,6 @@ abstract class Cpp2BeefGenerator
if (@block.HasValue) WriteBlock(@block.Value); if (@block.HasValue) WriteBlock(@block.Value);
} }
protected virtual bool FilterTokensBetweenCursors(CXToken token, out bool isWritingQueuedToken)
{
isWritingQueuedToken = false;
switch (Clang.GetTokenKind(token))
{
case .Comment:
case .Punctuation:
mixin QueuedToken(var queuedToken, StringView spelling)
{
if (fileInfo.queuedTokens.HasFlag(queuedToken) && GetTokenSpelling!(token) == spelling)
{
fileInfo.queuedTokens ^= queuedToken;
isWritingQueuedToken = true;
}
}
QueuedToken!(decltype(fileInfo.queuedTokens).LSquirly, "{");
QueuedToken!(decltype(fileInfo.queuedTokens).RSquirly, "}");
if (!fileInfo.queuedTokens.HasFlag(.RSquirly))
QueuedToken!(decltype(fileInfo.queuedTokens).Semicolon, ";");
if (!isWritingQueuedToken) return false;
default:
return false;
}
return true;
}
protected enum TypeParamMode { None, InParam, OutParam } protected enum TypeParamMode { None, InParam, OutParam }
protected virtual void Type(CXType type, TypeParamMode paramMode = .None) protected virtual void Type(CXType type, TypeParamMode paramMode = .None)
{ {
@@ -695,12 +692,12 @@ abstract class Cpp2BeefGenerator
case .StructDecl, .ClassDecl, .UnionDecl: Record(decl); case .StructDecl, .ClassDecl, .UnionDecl: Record(decl);
default: Internal.FatalError(scope $"Unhandled anon type: {_} {FatalErrorMsg(..scope .(256))}"); default: Internal.FatalError(scope $"Unhandled anon type: {_} {FatalErrorMsg(..scope .(256))}");
} }
if (fileInfo.queuedTokens.HasFlag(.RSquirly)) if (fileInfo.queuedRSquirly > 0)
{ {
str.Append('\n'); str.Append('\n');
GetIndentation(GetCursorAnchor(decl), str); GetIndentation(GetCursorAnchor(decl), str);
str.Append('}'); str.Append('}');
fileInfo.queuedTokens ^= .RSquirly; fileInfo.queuedRSquirly--;
} }
break; break;
} }
@@ -823,14 +820,8 @@ abstract class Cpp2BeefGenerator
protected mixin BeginBody(CXCursor cursor) protected mixin BeginBody(CXCursor cursor)
{ {
static void SetQueuedTokens(FileInfo fileInfo, FileInfo.QueuedTokens queuedTokens)
{
fileInfo.queuedTokens |= queuedTokens;
}
fileInfo.prevEnd = GetCursorAnchor(cursor); fileInfo.prevEnd = GetCursorAnchor(cursor);
defer:mixin SetQueuedTokens(fileInfo, fileInfo.queuedTokens); fileInfo.queuedLSquirly++;
fileInfo.queuedTokens = .LSquirly;
// [Friend] is needed in case you use BeginBody! in your code // [Friend] is needed in case you use BeginBody! in your code
if (canChangeBlock) if (canChangeBlock)
@@ -849,7 +840,7 @@ abstract class Cpp2BeefGenerator
this.[Friend]defferedWrapperWrite = null; this.[Friend]defferedWrapperWrite = null;
} }
if (fileInfo.queuedTokens.HasFlag(.LSquirly)) if (fileInfo.queuedLSquirly > 0)
{ {
switch (cursor.kind) switch (cursor.kind)
{ {
@@ -860,17 +851,16 @@ abstract class Cpp2BeefGenerator
default: default:
str.Append(" {}"); str.Append(" {}");
} }
fileInfo.queuedTokens = .None; fileInfo.queuedLSquirly--;
} }
else else
fileInfo.queuedTokens |= .RSquirly; fileInfo.queuedRSquirly++;
} }
} }
protected enum LinkageLanguage { C, Cpp } protected enum LinkageLanguage { C, Cpp }
protected virtual LinkageLanguage Linkable_Attributes(CXCursor cursor) protected virtual LinkageLanguage Linkable_Attributes(CXCursor cursor)
{ {
if (Flags.HasFlag(.Port)) return .C;
let mangledName = ScopeCXString!(Clang.Cursor_GetMangling(cursor)); let mangledName = ScopeCXString!(Clang.Cursor_GetMangling(cursor));
let name = GetNameInBindings(cursor, ..scope .(mangledName.Length)); let name = GetNameInBindings(cursor, ..scope .(mangledName.Length));
WriteCustomAttributes(cursor); WriteCustomAttributes(cursor);
@@ -928,7 +918,7 @@ abstract class Cpp2BeefGenerator
currentCursor = cursor; currentCursor = cursor;
} }
protected enum TypeAndNameKind { Standard, TypeAlias, ConversionFunction, Ctor, Dtor } protected enum TypeAndNameKind { Standard, TypeAlias, ConversionFunction, Ctor, Dtor, InvokeOperator }
protected virtual void WriteTypeAndName(CXCursor cursor, CXType type, TypeAndNameKind format = .Standard) protected virtual void WriteTypeAndName(CXCursor cursor, CXType type, TypeAndNameKind format = .Standard)
{ {
bool preserveColumns = Flags.HasFlag(.PreseveColumns); bool preserveColumns = Flags.HasFlag(.PreseveColumns);
@@ -976,6 +966,7 @@ abstract class Cpp2BeefGenerator
str.Append("operator", whitespace, typeStr, templateParams); str.Append("operator", whitespace, typeStr, templateParams);
case .Ctor: Internal.FatalError(scope $"unhandled ctor {FatalErrorMsg(..scope .(256))}"); case .Ctor: Internal.FatalError(scope $"unhandled ctor {FatalErrorMsg(..scope .(256))}");
case .Dtor: str.Append(whitespace, "Dispose"); case .Dtor: str.Append(whitespace, "Dispose");
case .InvokeOperator: str.Append(whitespace, "Invoke");
} }
} }
@@ -1107,35 +1098,6 @@ 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) protected virtual void FunctionDecl(CXCursor cursor)
{ {
Linkable_Attributes(cursor); Linkable_Attributes(cursor);
@@ -1146,7 +1108,7 @@ abstract class Cpp2BeefGenerator
Method_Parameters(cursor); Method_Parameters(cursor);
str.Append(')'); str.Append(')');
str.Append(templateParamsWhere); str.Append(templateParamsWhere);
PortCodeBody(cursor); str.Append(';');
} }
protected virtual void CXXMethod(CXCursor cursor) //TODO: conversion function protected virtual void CXXMethod(CXCursor cursor) //TODO: conversion function
@@ -1156,8 +1118,9 @@ abstract class Cpp2BeefGenerator
Linkable_Attributes(cursor); Linkable_Attributes(cursor);
} }
TypeAndNameKind invokeOperatorKind = .Standard;
let spelling = GetCursorSpelling!(cursor); let spelling = GetCursorSpelling!(cursor);
if (spelling.StartsWith("operator")) if (spelling.StartsWith("operator")) do
{ {
if (spelling == "operator[]") if (spelling == "operator[]")
{ {
@@ -1175,17 +1138,30 @@ abstract class Cpp2BeefGenerator
return; return;
} }
if (spelling == "operator()")
{
invokeOperatorKind = .InvokeOperator;
break;
}
int n = 0;
for (let c in spelling["operator".Length...])
if (c == '=')
n++;
Attributes(); Attributes();
AccessSpecifier(cursor); AccessSpecifier(cursor);
str.Append("static extern "); if (n != 1) str.Append("static ");
WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor), str.Append("extern ");
WriteTypeAndName(cursor, n == 1 ? .() { kind = .Void } : Clang.GetCursorResultType(cursor),
cursor.kind == .ConversionFunction ? .ConversionFunction : .Standard); cursor.kind == .ConversionFunction ? .ConversionFunction : .Standard);
str.Append("(in Self, "); str.Append('(');
if (n != 1) str.Append("in Self, ");
Method_Parameters(cursor); Method_Parameters(cursor);
if (str.EndsWith(", ")) str.Length -= 2; if (str.EndsWith(", ")) str.Length -= 2;
str.Append(')'); str.Append(')');
str.Append(templateParamsWhere); str.Append(templateParamsWhere);
PortCodeBody(cursor); str.Append(';');
return; return;
} }
@@ -1198,7 +1174,7 @@ abstract class Cpp2BeefGenerator
case .Constructor: WriteTypeAndName(cursor, default, .Ctor); case .Constructor: WriteTypeAndName(cursor, default, .Ctor);
case .Destructor: WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor), .Dtor); case .Destructor: WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor), .Dtor);
case .CXXMethod: case .CXXMethod:
WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor)); WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor), invokeOperatorKind);
default: default:
Internal.FatalError(scope $"Unhandled c++ method kind {FatalErrorMsg(..scope .(256))}"); Internal.FatalError(scope $"Unhandled c++ method kind {FatalErrorMsg(..scope .(256))}");
} }
@@ -1208,7 +1184,7 @@ abstract class Cpp2BeefGenerator
if (Clang.CXXMethod_IsStatic(cursor) == 0 && Clang.CXXMethod_IsConst(cursor) == 0 && cursor.kind == .CXXMethod) if (Clang.CXXMethod_IsStatic(cursor) == 0 && Clang.CXXMethod_IsConst(cursor) == 0 && cursor.kind == .CXXMethod)
str.Append(" mut"); str.Append(" mut");
str.Append(templateParamsWhere); str.Append(templateParamsWhere);
PortCodeBody(cursor); str.Append(';');
} }
int bitfieldUniquenessCounter = 0; int bitfieldUniquenessCounter = 0;
@@ -1289,16 +1265,7 @@ abstract class Cpp2BeefGenerator
WriteTypeAndName(cursor, type); WriteTypeAndName(cursor, type);
str.Append(';'); str.Append(';');
default: default:
if (Flags.HasFlag(.Port)) Internal.FatalError(scope $"Unhandled var linkage: {_} {FatalErrorMsg(..scope .(256))}");
{
AccessSpecifier(cursor);
str.Append("static ");
WriteTypeAndName(cursor, type);
WriteTokensAfterEquals(cursor);
str.Append(';');
}
else
Internal.FatalError(scope $"Unhandled var linkage: {_} {FatalErrorMsg(..scope .(256))}");
} }
} }
@@ -1322,9 +1289,8 @@ abstract class Cpp2BeefGenerator
protected virtual void Record(CXCursor cursor, bool attributes = true) protected virtual void Record(CXCursor cursor, bool attributes = true)
{ {
bool port = Flags.HasFlag(.Port);
WriteCustomAttributes(cursor); WriteCustomAttributes(cursor);
if (attributes && !port) if (attributes)
switch (cursor.kind) switch (cursor.kind)
{ {
case .StructDecl, .ClassDecl: str.Append("[CRepr] "); case .StructDecl, .ClassDecl: str.Append("[CRepr] ");
@@ -1332,21 +1298,20 @@ abstract class Cpp2BeefGenerator
default: Internal.FatalError(scope $"Unhandled record type {FatalErrorMsg(..scope .(256))}"); default: Internal.FatalError(scope $"Unhandled record type {FatalErrorMsg(..scope .(256))}");
} }
AccessSpecifier(cursor); AccessSpecifier(cursor);
if (cursor.kind == .ClassDecl && port) if (cursor.kind == .ClassDecl)
str.Append("class "); str.Append("class ");
else else
str.Append("struct "); str.Append("struct ");
if (Clang.Cursor_IsAnonymous(cursor) == 0) if (Clang.Cursor_IsAnonymous(cursor) == 0)
GetNameInBindings(cursor, str); GetNameInBindings(cursor, str);
str.Append(templateParams); str.Append(templateParams);
if (!port) Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
Clang.VisitChildren(cursor, (cursor, parent, client_data) => {
{ if (cursor.kind != .Destructor) return .Continue;
if (cursor.kind != .Destructor) return .Continue; String str = (.)Internal.UnsafeCastToObject(client_data);
String str = (.)Internal.UnsafeCastToObject(client_data); str.Append(" : IDisposable");
str.Append(" : IDisposable"); return .Break;
return .Break; }, Internal.UnsafeCastToPtr(str));
}, Internal.UnsafeCastToPtr(str));
str.Append(templateParamsWhere); str.Append(templateParamsWhere);
BeginBody!(cursor); BeginBody!(cursor);
@@ -1366,7 +1331,7 @@ abstract class Cpp2BeefGenerator
} }
}, Internal.UnsafeCastToPtr(this));*/ }, Internal.UnsafeCastToPtr(this));*/
if (!wrapperTemplateChain.IsEmpty && !port) if (!wrapperTemplateChain.IsEmpty)
{ {
//WriteQueuedOpenSquirly(); //WriteQueuedOpenSquirly();
str.Append("private const String __cpp_type = \"", GetCursorSpelling!(cursor), "<\""); str.Append("private const String __cpp_type = \"", GetCursorSpelling!(cursor), "<\"");
@@ -1409,29 +1374,20 @@ abstract class Cpp2BeefGenerator
if (Clang.IsVirtualBase(cursor) != 0) if (Clang.IsVirtualBase(cursor) != 0)
Internal.FatalError(scope $"Virtual bases are not supported {self.FatalErrorMsg(..scope .(256))}"); Internal.FatalError(scope $"Virtual bases are not supported {self.FatalErrorMsg(..scope .(256))}");
if (self.Flags.HasFlag(.Port)) //self.WriteQueuedOpenSquirly();
{ if (*firstBase && hasVTable && !HasVTable(Clang.GetCursorDefinition(cursor)))
if (*firstBase) self.str.Append(" : "); self.str.Append(self.cursorIndent, "private void* cppVtable;\n");
else self.str.Append(", "); self.str.Append(self.cursorIndent);
self.Type(Clang.GetCursorType(cursor)); self.AccessSpecifier(cursor);
} self.str.Append("using ");
else self.Type(Clang.GetCursorType(cursor));
{ self.str.Append(";\n");
//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; *firstBase = false;
return .Continue; return .Continue;
}, &(this, &firstBase, hasVTable)); }, &(this, &firstBase, hasVTable));
if (firstBase && hasVTable && !port) if (firstBase && hasVTable)
str.Append(cursorIndent, "private void* cppVtable;\n"); str.Append(cursorIndent, "private void* cppVtable;\n");
Clang.VisitChildren(cursor, (cursor, parent, client_data) => Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
@@ -1451,7 +1407,7 @@ abstract class Cpp2BeefGenerator
self.AccessSpecifier(cursor); self.AccessSpecifier(cursor);
self.str.Append("using "); self.str.Append("using ");
self.Record(cursor, attributes: false); self.Record(cursor, attributes: false);
self.fileInfo.queuedTokens |= .Semicolon; self.fileInfo.queuedSemicolon++;
} }
else else
self.WriteCursor(cursor); self.WriteCursor(cursor);