#include <clang-c/Index.h>
+#include "Bridge.hpp"
#include "Functor.hpp"
#include "Replace.hpp"
#include "Syntax.hpp"
return $ CYBlock(statements);
}
-static CYTypedIdentifier *CYDecodeType(CXType type);
-static void CYParseType(CXType type, CYTypedIdentifier *typed);
+static CYType *CYDecodeType(CXType type);
+static void CYParseType(CXType type, CYType *typed);
-static CYTypedIdentifier *CYDecodeType(CXType type, const CYCXString &identifier) {
- CYTypedIdentifier *typed(CYDecodeType(type));
- typed->identifier_ = $ CYIdentifier(identifier.Pool($pool));
- return typed;
+static void CYParseEnumeration(CXCursor cursor, CYType *typed) {
+ CYList<CYEnumConstant> constants;
+
+ CYForChild(cursor, fun([&](CXCursor child) {
+ if (clang_getCursorKind(child) == CXCursor_EnumConstantDecl)
+ constants->*$ CYEnumConstant($I($pool.strdup(CYCXString(child))), $D(clang_getEnumConstantDeclValue(child)));
+ }));
+
+ CYType *integer(CYDecodeType(clang_getEnumDeclIntegerType(cursor)));
+ typed->specifier_ = $ CYTypeEnum(NULL, integer->specifier_, constants);
}
-static void CYParseCursor(CXType type, CXCursor cursor, CYTypedIdentifier *typed) {
+static void CYParseStructure(CXCursor cursor, CYType *typed) {
+ CYList<CYTypeStructField> fields;
+ CYForChild(cursor, fun([&](CXCursor child) {
+ if (clang_getCursorKind(child) == CXCursor_FieldDecl)
+ fields->*$ CYTypeStructField(CYDecodeType(clang_getCursorType(child)), $I(CYCXString(child).Pool($pool)));
+ }));
+
+ typed->specifier_ = $ CYTypeStruct(NULL, $ CYStructTail(fields));
+}
+
+static void CYParseCursor(CXType type, CXCursor cursor, CYType *typed) {
CYCXString spelling(cursor);
switch (CXCursorKind kind = clang_getCursorKind(cursor)) {
case CXCursor_EnumDecl:
if (spelling[0] != '\0')
- // XXX: should we have a special enum keyword?
- typed->specifier_ = $ CYTypeVariable($I(spelling.Pool($pool)));
+ typed->specifier_ = $ CYTypeReference(CYTypeReferenceEnum, $I(spelling.Pool($pool)));
else
- // XXX: maybe replace with "enum : int" instead of "int"
- CYParseType(clang_getEnumDeclIntegerType(cursor), typed);
+ CYParseEnumeration(cursor, typed);
break;
case CXCursor_StructDecl: {
if (spelling[0] != '\0')
- typed->specifier_ = $ CYTypeReference($I(spelling.Pool($pool)));
- else {
- CYList<CYTypeStructField> fields;
- CYForChild(cursor, fun([&](CXCursor child) {
- if (clang_getCursorKind(child) == CXCursor_FieldDecl) {
- CYTypedIdentifier *field(CYDecodeType(clang_getCursorType(child), child));
- fields->*$ CYTypeStructField(field);
- }
- }));
-
- typed->specifier_ = $ CYTypeStruct(NULL, $ CYStructTail(fields));
- }
+ typed->specifier_ = $ CYTypeReference(CYTypeReferenceStruct, $I(spelling.Pool($pool)));
+ else
+ CYParseStructure(cursor, typed);
} break;
case CXCursor_UnionDecl: {
}
}
-static CYTypedParameter *CYParseSignature(CXType type, CYTypedIdentifier *typed) {
+static CYTypedParameter *CYParseSignature(CXType type, CYType *typed) {
CYParseType(clang_getResultType(type), typed);
CYList<CYTypedParameter> parameters;
for (int i(0), e(clang_getNumArgTypes(type)); i != e; ++i)
- parameters->*$ CYTypedParameter(CYDecodeType(clang_getArgType(type, i)));
+ parameters->*$ CYTypedParameter(CYDecodeType(clang_getArgType(type, i)), NULL);
return parameters;
}
-static void CYParseFunction(CXType type, CYTypedIdentifier *typed) {
+static void CYParseFunction(CXType type, CYType *typed) {
typed = typed->Modify($ CYTypeFunctionWith(clang_isFunctionTypeVariadic(type), CYParseSignature(type, typed)));
}
-static void CYParseType(CXType type, CYTypedIdentifier *typed) {
+static void CYParseType(CXType type, CYType *typed) {
switch (CXTypeKind kind = type.kind) {
case CXType_Unexposed: {
CXType result(clang_getResultType(type));
} break;
case CXType_Bool: typed->specifier_ = $ CYTypeVariable("bool"); break;
- case CXType_Float: typed->specifier_ = $ CYTypeVariable("float"); break;
- case CXType_Double: typed->specifier_ = $ CYTypeVariable("double"); break;
+ case CXType_WChar: typed->specifier_ = $ CYTypeVariable("wchar_t"); break;
+ case CXType_Float: typed->specifier_ = $ CYTypeFloating(0); break;
+ case CXType_Double: typed->specifier_ = $ CYTypeFloating(1); break;
+ case CXType_LongDouble: typed->specifier_ = $ CYTypeFloating(2); break;
case CXType_Char_U: typed->specifier_ = $ CYTypeCharacter(CYTypeNeutral); break;
case CXType_Char_S: typed->specifier_ = $ CYTypeCharacter(CYTypeNeutral); break;
break;
case CXType_IncompleteArray:
- // XXX: I should support these :/
- _assert(false);
+ // XXX: I probably should not decay to Pointer
+ CYParseType(clang_getArrayElementType(type), typed);
+ typed = typed->Modify($ CYTypePointerTo());
+ break;
+
+ case CXType_ObjCClass:
+ typed->specifier_ = $ CYTypeVariable("Class");
break;
case CXType_ObjCId:
break;
case CXType_Record:
- typed->specifier_ = $ CYTypeReference($I($pool.strdup(CYCXString(clang_getTypeSpelling(type)))));
+ typed->specifier_ = $ CYTypeReference(CYTypeReferenceStruct, $I($pool.strdup(CYCXString(clang_getTypeSpelling(type)))));
break;
case CXType_Typedef:
typed = typed->Modify($ CYTypeConstant());
}
-static CYTypedIdentifier *CYDecodeType(CXType type) {
- CYTypedIdentifier *typed($ CYTypedIdentifier(NULL));
+static CYType *CYDecodeType(CXType type) {
+ CYType *typed($ CYType(NULL));
CYParseType(type, typed);
return typed;
}
CYChildBaton &baton(*static_cast<CYChildBaton *>(arg));
CXTranslationUnit &unit(baton.unit);
+ CXChildVisitResult result(CXChildVisit_Continue);
CYCXString spelling(cursor);
std::string name(spelling);
std::ostringstream value;
unsigned priority(2);
- unsigned flags(0);
+ unsigned flags(CYBridgeHold);
/*CXSourceLocation location(clang_getCursorLocation(cursor));
CYCXPosition<> position(location);
std::cerr << spelling << " " << position << std::endl;*/
- switch (CXCursorKind kind = clang_getCursorKind(cursor)) {
+ try { switch (CXCursorKind kind = clang_getCursorKind(cursor)) {
case CXCursor_EnumConstantDecl: {
value << clang_getEnumConstantDeclValue(cursor);
} break;
- case CXCursor_MacroDefinition: try {
+ case CXCursor_EnumDecl: {
+ if (spelling[0] == '\0')
+ goto skip;
+ // XXX: this was blindly copied from StructDecl
+ if (!clang_isCursorDefinition(cursor))
+ priority = 1;
+
+ CYLocalPool pool;
+
+ CYType typed;
+ CYParseEnumeration(cursor, &typed);
+
+ CYOptions options;
+ CYOutput out(*value.rdbuf(), options);
+ CYTypeExpression(&typed).Output(out, CYNoBFC);
+
+ value << ".withName(\"" << name << "\")";
+ name = "$cye" + name;
+ flags = CYBridgeType;
+
+ // the enum constants are implemented separately *also*
+ // XXX: maybe move output logic to function we can call
+ result = CXChildVisit_Recurse;
+ } break;
+
+ case CXCursor_MacroDefinition: {
CXSourceRange range(clang_getCursorExtent(cursor));
CYTokens tokens(unit, range);
_assert(tokens.size() != 0);
value << body.str();
out << ';' << '}' << ')';
}
- } catch (const CYException &error) {
- CYPool pool;
- //std::cerr << error.PoolCString(pool) << std::endl;
- goto skip;
} break;
case CXCursor_StructDecl: {
if (!clang_isCursorDefinition(cursor))
priority = 1;
- std::ostringstream types;
- std::ostringstream names;
+ CYLocalPool pool;
- CYForChild(cursor, fun([&](CXCursor child) {
- if (clang_getCursorKind(child) == CXCursor_FieldDecl) {
- CXType type(clang_getCursorType(child));
- types << "(typedef " << CYCXString(clang_getTypeSpelling(type)) << "),";
- names << "'" << CYCXString(child) << "',";
- }
- }));
+ CYType typed;
+ CYParseStructure(cursor, &typed);
+
+ CYOptions options;
+ CYOutput out(*value.rdbuf(), options);
+ CYTypeExpression(&typed).Output(out, CYNoBFC);
- value << "new Type([" << types.str() << "],[" << names.str() << "]).withName(\"" << name << "\")";
- name += "$cy";
+ value << ".withName(\"" << name << "\")";
+ name = "$cys" + name;
+ flags = CYBridgeType;
} break;
- case CXCursor_TypedefDecl: try {
+ case CXCursor_TypedefDecl: {
CYLocalPool local;
- CYTypedIdentifier *typed(CYDecodeType(clang_getTypedefDeclUnderlyingType(cursor)));
+ CYType *typed(CYDecodeType(clang_getTypedefDeclUnderlyingType(cursor)));
if (typed->specifier_ == NULL)
value << "(typedef " << CYCXString(clang_getTypeSpelling(clang_getTypedefDeclUnderlyingType(cursor))) << ")";
else {
CYOutput out(*value.rdbuf(), options);
CYTypeExpression(typed).Output(out, CYNoBFC);
}
- } catch (const CYException &error) {
- CYPool pool;
- //std::cerr << error.PoolCString(pool) << std::endl;
- goto skip;
} break;
case CXCursor_FunctionDecl:
- case CXCursor_VarDecl: try {
+ case CXCursor_VarDecl: {
std::string label;
CYList<CYFunctionParameter> parameters;
goto skip;
if (code == NULL) {
+ value << "*";
CXType type(clang_getCursorType(cursor));
- value << "*(typedef " << CYCXString(clang_getTypeSpelling(type)) << ").pointerTo()(dlsym(RTLD_DEFAULT,'" << label.substr(1) << "'))";
+ CYType *typed(CYDecodeType(type));
+ CYOptions options;
+ CYOutput out(*value.rdbuf(), options);
+ CYTypeExpression(typed).Output(out, CYNoBFC);
+ value << ".pointerTo()(dlsym(RTLD_DEFAULT,'" << label.substr(1) << "'))";
} else {
CYOptions options;
CYOutput out(*value.rdbuf(), options);
function->Output(out, CYNoBFC);
//std::cerr << value.str() << std::endl;
}
- } catch (const CYException &error) {
- CYPool pool;
- //std::cerr << error.PoolCString(pool) << std::endl;
- goto skip;
- } break;
-
- default: {
- return CXChildVisit_Recurse;
} break;
- }
- {
+ default:
+ result = CXChildVisit_Recurse;
+ goto skip;
+ break;
+ } {
CYKey &key(baton.keys[name]);
if (key.priority_ <= priority) {
key.priority_ = priority;
key.code_ = value.str();
key.flags_ = flags;
}
+ } } catch (const CYException &error) {
+ CYPool pool;
+ //std::cerr << error.PoolCString(pool) << std::endl;
}
skip:
- return CXChildVisit_Continue;
+ return result;
}
int main(int argc, const char *argv[]) {