Caa/src/Binding.bf

165 lines
No EOL
4.9 KiB
Beef

namespace Caa;
using System;
using System.Collections;
using libclang_beef;
class Binding
{
public static List<BindingFunction> Function = new .() ~ DeleteContainerAndItems!(_);
public static List<BindingEnum> Enums = new .() ~ DeleteContainerAndItems!(_);
public static List<BindingStruct> Structs = new .() ~ DeleteContainerAndItems!(_);
public static BindingOptions Options = new .() ~ delete _;
public static Dictionary<CXCursorKind, function void(CXCursor*)> CursorHandlers = new .() {
(.CXCursor_FunctionDecl, => HandleFunctionDecl),
(.CXCursor_StructDecl, => HandleStructDecl),
(.CXCursor_FieldDecl, => HandleFieldDecl),
(.CXCursor_EnumDecl, => HandleEnumDecl),
(.CXCursor_EnumConstantDecl, => HandleEnumConstDecl),
(.CXCursor_ParmDecl, => DoNothing),
} ~ delete _;
public static void Bind(ref String[] pArgs)
{
CXIndex index = clang_createIndex(0, 0);
CXTranslationUnit* unit;
clang_parseTranslationUnit2(
index,
pArgs[0], //TODO: This is a hack, allegedly it would be fine if we just input the file as an arg but that doesnt seem to work
(.)&pArgs, (.)pArgs.Count, null, 0,
(.)CXTranslationUnit_Flags.CXTranslationUnit_None,
out unit
);
//TODO: Error Handling
CXCursor cursor = clang_getTranslationUnitCursor(*unit);
clang_visitChildren(
cursor,
(cursor, parent, client_data) => {
switch(clang_getCursorKind(cursor))
{
case .CXCursor_FunctionDecl:
var name = clang_getCursorSpelling(cursor);
BindingFunction func = new .(name.text, clang_getCursorResultType(cursor));
var count = clang_Cursor_getNumArguments(cursor);
for(int i < count)
{
var arg = clang_Cursor_getArgument(cursor, (.)i);
var argType = clang_getCursorType(arg);
var argName = clang_getCursorSpelling(arg);
func.Args.Add(new .(argName.text, argType));
}
Function.Add(func);
case .CXCursor_StructDecl:
var name = clang_getCursorSpelling(cursor);
BindingStruct strct = new .(name.text);
Structs.Add(strct);
case .CXCursor_FieldDecl:
if(Structs.Count > 0)
Structs[Structs.Count-1].Fields.Add(new .(clang_getCursorSpelling(cursor).text, clang_getCursorType(cursor)));
case .CXCursor_EnumDecl:
var name = clang_getCursorSpelling(cursor);
BindingEnum enm = new .(name.text);
Enums.Add(enm);
case .CXCursor_EnumConstantDecl:
if(Enums.Count > 0)
Enums[Enums.Count-1].Entries.Add(new .(clang_getCursorSpelling(cursor).text, (.)clang_getEnumConstantDeclValue(cursor)));
case .CXCursor_ParmDecl:
DoNothing(&cursor);
default:
Console.WriteLine(scope $"{clang_getCursorKind(cursor)} {clang_getCursorSpelling(cursor).text}");
}
/*
if(CursorHandlers.ContainsKey(clang_getCursorKind(cursor)))
CursorHandlers[clang_getCursorKind(cursor)](&cursor);
else
Console.WriteLine(scope $"{clang_getCursorKind(cursor)} {clang_getCursorSpelling(cursor).text}");
*/
return CXChildVisitResult.CXChildVisit_Recurse;
}, null );
clang_disposeTranslationUnit(*unit);
clang_disposeIndex(index);
}
public static void HandleFunctionDecl(CXCursor* cursor)
{
var name = clang_getCursorSpelling(*cursor);
BindingFunction func = new .(name.text, clang_getCursorResultType(*cursor));
var count = clang_Cursor_getNumArguments(*cursor);
for(int i < count)
{
var arg = clang_Cursor_getArgument(*cursor, (.)i);
var argType = clang_getCursorType(arg);
var argName = clang_getCursorSpelling(arg);
func.Args.Add(new .(argName.text, argType));
}
Function.Add(func);
}
public static void HandleStructDecl(CXCursor* cursor)
{
var name = clang_getCursorSpelling(*cursor);
BindingStruct strct = new .(name.text);
Structs.Add(strct);
}
public static void HandleFieldDecl(CXCursor* cursor)
{
if(Structs.Count > 0)
Structs[Structs.Count-1].Fields.Add(new .(clang_getCursorSpelling(*cursor).text, clang_getCursorType(*cursor)));
}
public static void HandleEnumDecl(CXCursor* cursor)
{
var name = clang_getCursorSpelling(*cursor);
BindingEnum enm = new .(name.text);
Enums.Add(enm);
}
public static void HandleEnumConstDecl(CXCursor* cursor)
{
if(Enums.Count > 0)
{
Enums[Enums.Count-1].Entries.Add(new .(clang_getCursorSpelling(*cursor).text, (.)clang_getEnumConstantDeclValue(*cursor)));
}
}
private static void DoNothing(CXCursor* cursor) {}
///Generate the actual file strings and try to write them according to the input parameter and the options
public static Result<void> Generate(StringView pOutputDir = "")
{
if(pOutputDir == "")
return .Err;
String toWrite = new .(scope $"""
namespace {Binding.Options.Namespace};
static
\{\n
""");
defer delete toWrite;
for(var i in Function)
i.ToBeef(toWrite);
for(var i in Structs)
i.ToBeef(toWrite);
for(var i in Enums)
i.ToBeef(toWrite);
toWrite.Append("\n}");
return System.IO.File.WriteAllText(pOutputDir, toWrite);
}
}