discont ports & change token queueing
This commit is contained in:
+76
-120
@@ -17,9 +17,6 @@ abstract class Cpp2BeefGenerator
|
||||
{
|
||||
None = 0,
|
||||
PreseveColumns = 1,
|
||||
|
||||
/// WIP
|
||||
Port = 2,
|
||||
}
|
||||
|
||||
protected virtual void GetNameInBindings(CXCursor cursor, String outString)
|
||||
@@ -182,8 +179,11 @@ abstract class Cpp2BeefGenerator
|
||||
MacroDefinition(cursor);
|
||||
|
||||
case .InclusionDirective, .MacroExpansion, .CXXBaseSpecifier, .CXXAccessSpecifier,
|
||||
.LinkageSpec, .TemplateTypeParameter, .NonTypeTemplateParameter, .StaticAssert: // ignored
|
||||
default: Debug.WriteLine(scope $"Unhandled cursor: {_}");
|
||||
.LinkageSpec, .TemplateTypeParameter, .NonTypeTemplateParameter, .StaticAssert,
|
||||
.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 append String wrapperTemplateChain = .(16);
|
||||
private append String templateParams = .(16);
|
||||
private append String templateParamsWhere = .(64);
|
||||
public append String templateParams = .(16);
|
||||
public append String templateParamsWhere = .(64);
|
||||
private String defferedWrapperWrite = null;
|
||||
|
||||
private struct UnitMacroIndex : this(uint32 line, CXFile file), IHashable
|
||||
@@ -228,10 +228,13 @@ abstract class Cpp2BeefGenerator
|
||||
}
|
||||
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 QueuedTokens queuedTokens = .None;
|
||||
public (CXType type, int32 curWidth) bitfield = default;
|
||||
}
|
||||
protected FileInfo fileInfo = null;
|
||||
@@ -300,8 +303,7 @@ abstract class Cpp2BeefGenerator
|
||||
Runtime.FatalError("You must set a language via Args (e.g. --language=c++)");
|
||||
}
|
||||
#endif
|
||||
CXTranslationUnit_Flags unitFlags = .DetailedPreprocessingRecord;
|
||||
if (!Flags.HasFlag(.Port)) unitFlags |= .SkipFunctionBodies;
|
||||
CXTranslationUnit_Flags unitFlags = .DetailedPreprocessingRecord | .SkipFunctionBodies;
|
||||
unit = Clang.ParseTranslationUnit(index, headerPath, args.Ptr, (.)args.Length, null, 0, (.)unitFlags);
|
||||
if (unit == default) return .Err(.ParsingFailed);
|
||||
|
||||
@@ -516,13 +518,13 @@ abstract class Cpp2BeefGenerator
|
||||
protected virtual void WriteComments(CXSourceLocation writeUntil, Block? block = null)
|
||||
{
|
||||
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(fileInfo.prevEnd, let prevFile, let prevLine, let prevColumn, let prevOffset);
|
||||
|
||||
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))}");
|
||||
|
||||
var between = Clang.GetRange(
|
||||
@@ -564,7 +566,7 @@ abstract class Cpp2BeefGenerator
|
||||
|
||||
void Block()
|
||||
{
|
||||
if (fileInfo.queuedTokens != .None) return;
|
||||
if (!fileInfo.NoTokensQueued) return;
|
||||
findMacros: do
|
||||
{
|
||||
for (uint32 ln = line; ln < curLine; ln++)
|
||||
@@ -578,11 +580,34 @@ abstract class Cpp2BeefGenerator
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
bool isWritingQueuedToken = false;
|
||||
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;
|
||||
if (isWritingQueuedToken && fileInfo.queuedTokens == .None)
|
||||
}
|
||||
if (isWritingQueuedToken && fileInfo.NoTokensQueued)
|
||||
block = @block;
|
||||
let location = Clang.GetTokenLocation(unit, token);
|
||||
Clang.GetFileLocation(location, ?, let startLine, ?, ?);
|
||||
@@ -602,34 +627,6 @@ abstract class Cpp2BeefGenerator
|
||||
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 virtual void Type(CXType type, TypeParamMode paramMode = .None)
|
||||
{
|
||||
@@ -695,12 +692,12 @@ abstract class Cpp2BeefGenerator
|
||||
case .StructDecl, .ClassDecl, .UnionDecl: Record(decl);
|
||||
default: Internal.FatalError(scope $"Unhandled anon type: {_} {FatalErrorMsg(..scope .(256))}");
|
||||
}
|
||||
if (fileInfo.queuedTokens.HasFlag(.RSquirly))
|
||||
if (fileInfo.queuedRSquirly > 0)
|
||||
{
|
||||
str.Append('\n');
|
||||
GetIndentation(GetCursorAnchor(decl), str);
|
||||
str.Append('}');
|
||||
fileInfo.queuedTokens ^= .RSquirly;
|
||||
fileInfo.queuedRSquirly--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -823,14 +820,8 @@ abstract class Cpp2BeefGenerator
|
||||
|
||||
protected mixin BeginBody(CXCursor cursor)
|
||||
{
|
||||
static void SetQueuedTokens(FileInfo fileInfo, FileInfo.QueuedTokens queuedTokens)
|
||||
{
|
||||
fileInfo.queuedTokens |= queuedTokens;
|
||||
}
|
||||
|
||||
fileInfo.prevEnd = GetCursorAnchor(cursor);
|
||||
defer:mixin SetQueuedTokens(fileInfo, fileInfo.queuedTokens);
|
||||
fileInfo.queuedTokens = .LSquirly;
|
||||
fileInfo.queuedLSquirly++;
|
||||
|
||||
// [Friend] is needed in case you use BeginBody! in your code
|
||||
if (canChangeBlock)
|
||||
@@ -849,7 +840,7 @@ abstract class Cpp2BeefGenerator
|
||||
this.[Friend]defferedWrapperWrite = null;
|
||||
}
|
||||
|
||||
if (fileInfo.queuedTokens.HasFlag(.LSquirly))
|
||||
if (fileInfo.queuedLSquirly > 0)
|
||||
{
|
||||
switch (cursor.kind)
|
||||
{
|
||||
@@ -860,17 +851,16 @@ abstract class Cpp2BeefGenerator
|
||||
default:
|
||||
str.Append(" {}");
|
||||
}
|
||||
fileInfo.queuedTokens = .None;
|
||||
fileInfo.queuedLSquirly--;
|
||||
}
|
||||
else
|
||||
fileInfo.queuedTokens |= .RSquirly;
|
||||
fileInfo.queuedRSquirly++;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -928,7 +918,7 @@ abstract class Cpp2BeefGenerator
|
||||
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)
|
||||
{
|
||||
bool preserveColumns = Flags.HasFlag(.PreseveColumns);
|
||||
@@ -976,6 +966,7 @@ abstract class Cpp2BeefGenerator
|
||||
str.Append("operator", whitespace, typeStr, templateParams);
|
||||
case .Ctor: Internal.FatalError(scope $"unhandled ctor {FatalErrorMsg(..scope .(256))}");
|
||||
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)
|
||||
{
|
||||
Linkable_Attributes(cursor);
|
||||
@@ -1146,7 +1108,7 @@ abstract class Cpp2BeefGenerator
|
||||
Method_Parameters(cursor);
|
||||
str.Append(')');
|
||||
str.Append(templateParamsWhere);
|
||||
PortCodeBody(cursor);
|
||||
str.Append(';');
|
||||
}
|
||||
|
||||
protected virtual void CXXMethod(CXCursor cursor) //TODO: conversion function
|
||||
@@ -1156,8 +1118,9 @@ abstract class Cpp2BeefGenerator
|
||||
Linkable_Attributes(cursor);
|
||||
}
|
||||
|
||||
TypeAndNameKind invokeOperatorKind = .Standard;
|
||||
let spelling = GetCursorSpelling!(cursor);
|
||||
if (spelling.StartsWith("operator"))
|
||||
if (spelling.StartsWith("operator")) do
|
||||
{
|
||||
if (spelling == "operator[]")
|
||||
{
|
||||
@@ -1175,17 +1138,30 @@ abstract class Cpp2BeefGenerator
|
||||
return;
|
||||
}
|
||||
|
||||
if (spelling == "operator()")
|
||||
{
|
||||
invokeOperatorKind = .InvokeOperator;
|
||||
break;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
for (let c in spelling["operator".Length...])
|
||||
if (c == '=')
|
||||
n++;
|
||||
|
||||
Attributes();
|
||||
AccessSpecifier(cursor);
|
||||
str.Append("static extern ");
|
||||
WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor),
|
||||
if (n != 1) str.Append("static ");
|
||||
str.Append("extern ");
|
||||
WriteTypeAndName(cursor, n == 1 ? .() { kind = .Void } : Clang.GetCursorResultType(cursor),
|
||||
cursor.kind == .ConversionFunction ? .ConversionFunction : .Standard);
|
||||
str.Append("(in Self, ");
|
||||
str.Append('(');
|
||||
if (n != 1) str.Append("in Self, ");
|
||||
Method_Parameters(cursor);
|
||||
if (str.EndsWith(", ")) str.Length -= 2;
|
||||
str.Append(')');
|
||||
str.Append(templateParamsWhere);
|
||||
PortCodeBody(cursor);
|
||||
str.Append(';');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1198,7 +1174,7 @@ abstract class Cpp2BeefGenerator
|
||||
case .Constructor: WriteTypeAndName(cursor, default, .Ctor);
|
||||
case .Destructor: WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor), .Dtor);
|
||||
case .CXXMethod:
|
||||
WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor));
|
||||
WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor), invokeOperatorKind);
|
||||
default:
|
||||
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)
|
||||
str.Append(" mut");
|
||||
str.Append(templateParamsWhere);
|
||||
PortCodeBody(cursor);
|
||||
str.Append(';');
|
||||
}
|
||||
|
||||
int bitfieldUniquenessCounter = 0;
|
||||
@@ -1289,15 +1265,6 @@ abstract class Cpp2BeefGenerator
|
||||
WriteTypeAndName(cursor, type);
|
||||
str.Append(';');
|
||||
default:
|
||||
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))}");
|
||||
}
|
||||
}
|
||||
@@ -1322,9 +1289,8 @@ abstract class Cpp2BeefGenerator
|
||||
|
||||
protected virtual void Record(CXCursor cursor, bool attributes = true)
|
||||
{
|
||||
bool port = Flags.HasFlag(.Port);
|
||||
WriteCustomAttributes(cursor);
|
||||
if (attributes && !port)
|
||||
if (attributes)
|
||||
switch (cursor.kind)
|
||||
{
|
||||
case .StructDecl, .ClassDecl: str.Append("[CRepr] ");
|
||||
@@ -1332,14 +1298,13 @@ abstract class Cpp2BeefGenerator
|
||||
default: Internal.FatalError(scope $"Unhandled record type {FatalErrorMsg(..scope .(256))}");
|
||||
}
|
||||
AccessSpecifier(cursor);
|
||||
if (cursor.kind == .ClassDecl && port)
|
||||
if (cursor.kind == .ClassDecl)
|
||||
str.Append("class ");
|
||||
else
|
||||
str.Append("struct ");
|
||||
if (Clang.Cursor_IsAnonymous(cursor) == 0)
|
||||
GetNameInBindings(cursor, str);
|
||||
str.Append(templateParams);
|
||||
if (!port)
|
||||
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
|
||||
{
|
||||
if (cursor.kind != .Destructor) return .Continue;
|
||||
@@ -1366,7 +1331,7 @@ abstract class Cpp2BeefGenerator
|
||||
}
|
||||
}, Internal.UnsafeCastToPtr(this));*/
|
||||
|
||||
if (!wrapperTemplateChain.IsEmpty && !port)
|
||||
if (!wrapperTemplateChain.IsEmpty)
|
||||
{
|
||||
//WriteQueuedOpenSquirly();
|
||||
str.Append("private const String __cpp_type = \"", GetCursorSpelling!(cursor), "<\"");
|
||||
@@ -1409,14 +1374,6 @@ abstract class Cpp2BeefGenerator
|
||||
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");
|
||||
@@ -1425,13 +1382,12 @@ abstract class Cpp2BeefGenerator
|
||||
self.str.Append("using ");
|
||||
self.Type(Clang.GetCursorType(cursor));
|
||||
self.str.Append(";\n");
|
||||
}
|
||||
|
||||
*firstBase = false;
|
||||
return .Continue;
|
||||
}, &(this, &firstBase, hasVTable));
|
||||
|
||||
if (firstBase && hasVTable && !port)
|
||||
if (firstBase && hasVTable)
|
||||
str.Append(cursorIndent, "private void* cppVtable;\n");
|
||||
|
||||
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
|
||||
@@ -1451,7 +1407,7 @@ abstract class Cpp2BeefGenerator
|
||||
self.AccessSpecifier(cursor);
|
||||
self.str.Append("using ");
|
||||
self.Record(cursor, attributes: false);
|
||||
self.fileInfo.queuedTokens |= .Semicolon;
|
||||
self.fileInfo.queuedSemicolon++;
|
||||
}
|
||||
else
|
||||
self.WriteCursor(cursor);
|
||||
|
||||
Reference in New Issue
Block a user