X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/d9241e234c470731820076c7f38b73a09ecb7627..307a439f88889d960e82d98c5765cca7ea5df321:/Analyze.cpp diff --git a/Analyze.cpp b/Analyze.cpp index 922dfb1..9a056e5 100644 --- a/Analyze.cpp +++ b/Analyze.cpp @@ -28,6 +28,7 @@ #include +#include "Bridge.hpp" #include "Functor.hpp" #include "Replace.hpp" #include "Syntax.hpp" @@ -288,42 +289,47 @@ static CYStatement *CYTranslateBlock(CXTranslationUnit unit, CXCursor cursor) { 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 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 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 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: { @@ -337,19 +343,19 @@ static void CYParseCursor(CXType type, CXCursor cursor, CYTypedIdentifier *typed } } -static CYTypedParameter *CYParseSignature(CXType type, CYTypedIdentifier *typed) { +static CYTypedParameter *CYParseSignature(CXType type, CYType *typed) { CYParseType(clang_getResultType(type), typed); CYList 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)); @@ -361,8 +367,10 @@ static void CYParseType(CXType type, CYTypedIdentifier *typed) { } 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; @@ -381,6 +389,9 @@ static void CYParseType(CXType type, CYTypedIdentifier *typed) { case CXType_LongLong: typed->specifier_ = $ CYTypeIntegral(CYTypeSigned, 3); break; case CXType_ULongLong: typed->specifier_ = $ CYTypeIntegral(CYTypeUnsigned, 3); break; + case CXType_Int128: typed->specifier_ = $ CYTypeInt128(CYTypeSigned); break; + case CXType_UInt128: typed->specifier_ = $ CYTypeInt128(CYTypeUnsigned); break; + case CXType_BlockPointer: { CXType pointee(clang_getPointeeType(type)); _assert(!clang_isFunctionTypeVariadic(pointee)); @@ -401,8 +412,13 @@ static void CYParseType(CXType type, CYTypedIdentifier *typed) { 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: @@ -433,7 +449,7 @@ static void CYParseType(CXType type, CYTypedIdentifier *typed) { 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: @@ -459,8 +475,8 @@ static void CYParseType(CXType type, CYTypedIdentifier *typed) { 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; } @@ -469,22 +485,48 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien CYChildBaton &baton(*static_cast(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: { + // the enum constants are implemented separately *also* + // XXX: maybe move output logic to function we can call + result = CXChildVisit_Recurse; + + 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; + } break; + + case CXCursor_MacroDefinition: { CXSourceRange range(clang_getCursorExtent(cursor)); CYTokens tokens(unit, range); _assert(tokens.size() != 0); @@ -537,10 +579,6 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien value << body.str(); out << ';' << '}' << ')'; } - } catch (const CYException &error) { - CYPool pool; - //std::cerr << error.PoolCString(pool) << std::endl; - goto skip; } break; case CXCursor_StructDecl: { @@ -549,25 +587,24 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien 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 { @@ -575,14 +612,10 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien 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 parameters; @@ -623,8 +656,13 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien 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); @@ -632,28 +670,26 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien 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) { + 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[]) {